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) {
101 PrintError("Long mode currently not handled\n");
105 struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
106 struct cr0_32 *new_cr0= (struct cr0_32 *)(dec_instr.src_operand.operand);
108 PrintDebug("OperandVal = %x, length=%d\n", *(uint_t *)new_cr0, dec_instr.src_operand.size);
111 PrintDebug("Old CR0=%x\n", *(uint_t *)real_cr0);
112 *real_cr0 = *new_cr0;
115 if (info->shdw_pg_mode == SHADOW_PAGING) {
116 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
118 PrintDebug("Old Shadow CR0=%x\n", *(uint_t *)shadow_cr0);
122 *shadow_cr0 = *new_cr0;
125 if (v3_get_mem_mode(info) == VIRTUAL_MEM) {
126 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
127 PrintDebug("Setting up Shadow Page Table\n");
128 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
130 info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
134 PrintDebug("New Shadow CR0=%x\n",*(uint_t *)shadow_cr0);
136 PrintDebug("New CR0=%x\n", *(uint_t *)real_cr0);
139 } else if (v3_opcode_cmp(V3_OPCODE_CLTS, (const uchar_t *)(dec_instr.opcode)) == 0) {
141 struct cr0_32 *real_cr0 = (struct cr0_32*)&(info->ctrl_regs.cr0);
145 if (info->shdw_pg_mode == SHADOW_PAGING) {
146 struct cr0_32 * shadow_cr0 = (struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
150 PrintError("Unhandled opcode in handle_cr0_write\n");
154 info->rip += dec_instr.instr_length;
160 // First attempt = 253 lines
161 // current = 51 lines
162 int v3_handle_cr0_read(struct guest_info * info) {
165 struct x86_instr dec_instr;
167 if (info->mem_mode == PHYSICAL_MEM) {
168 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
170 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
173 /* The IFetch will already have faulted in the necessary bytes for the full instruction
175 // I think we should inject a GPF into the guest
176 PrintError("Could not read instruction (ret=%d)\n", ret);
181 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
182 PrintError("Could not decode instruction\n");
186 if (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
187 struct cr0_32 * virt_cr0 = (struct cr0_32 *)(dec_instr.dst_operand.operand);
188 struct cr0_32 * real_cr0 = (struct cr0_32 *)&(info->ctrl_regs.cr0);
190 PrintDebug("MOVCR2\n");
191 PrintDebug("CR0 at 0x%p\n", (void *)real_cr0);
193 if (info->shdw_pg_mode == SHADOW_PAGING) {
194 *virt_cr0 = *(struct cr0_32 *)&(info->shdw_pg_state.guest_cr0);
196 *virt_cr0 = *real_cr0;
199 PrintDebug("real CR0: %x\n", *(uint_t*)real_cr0);
200 PrintDebug("returned CR0: %x\n", *(uint_t*)virt_cr0);
201 } else if (v3_opcode_cmp(V3_OPCODE_SMSW, (const uchar_t *)(dec_instr.opcode)) == 0) {
202 struct cr0_real *real_cr0= (struct cr0_real*)&(info->ctrl_regs.cr0);
203 struct cr0_real *virt_cr0 = (struct cr0_real *)(dec_instr.dst_operand.operand);
204 char cr0_val = *(char*)real_cr0 & 0x0f;
206 PrintDebug("SMSW\n");
208 PrintDebug("CR0 at 0x%p\n", real_cr0);
210 *(char *)virt_cr0 &= 0xf0;
211 *(char *)virt_cr0 |= cr0_val;
214 PrintError("Unhandled opcode in handle_cr0_read\n");
218 info->rip += dec_instr.instr_length;
225 // First Attempt = 256 lines
226 // current = 65 lines
227 int v3_handle_cr3_write(struct guest_info * info) {
230 struct x86_instr dec_instr;
232 if (info->mem_mode == PHYSICAL_MEM) {
233 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
235 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
238 /* The IFetch will already have faulted in the necessary bytes for the full instruction
240 // I think we should inject a GPF into the guest
241 PrintError("Could not read instruction (ret=%d)\n", ret);
246 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
247 PrintError("Could not decode instruction\n");
251 if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) == 0) {
253 PrintDebug("MOV2CR3\n");
255 PrintDebug("CR3 at 0x%p\n", &(info->ctrl_regs.cr3));
257 if (info->shdw_pg_mode == SHADOW_PAGING) {
258 struct cr3_32 * new_cr3 = (struct cr3_32 *)(dec_instr.src_operand.operand);
259 struct cr3_32 * guest_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
260 struct cr3_32 * shadow_cr3 = (struct cr3_32 *)&(info->shdw_pg_state.shadow_cr3);
264 PrintDebug("Old Shadow CR3=%x; Old Guest CR3=%x\n",
265 *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
269 cached = v3_cache_page_tables32(info, (addr_t)V3_PAddr((void *)(addr_t)CR3_TO_PDE32((void *)*(addr_t *)new_cr3)));
272 PrintError("CR3 Cache failed\n");
274 } else if (cached == 0) {
277 if(info->mem_mode == VIRTUAL_MEM) {
278 PrintDebug("New CR3 is different - flushing shadow page table %p\n", shadow_cr3 );
279 delete_page_tables_32((pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3));
282 shadow_pt = v3_create_new_shadow_pt();
284 shadow_cr3->pdt_base_addr = (addr_t)V3_PAddr((void *)(addr_t)PD32_BASE_ADDR(shadow_pt));
285 PrintDebug( "Created new shadow page table %p\n", (void *)(addr_t)shadow_cr3->pdt_base_addr );
286 //PrintDebugPageTables( (pde32_t *)CR3_TO_PDE32(*(uint_t*)shadow_cr3) );
290 PrintDebug("Reusing cached shadow Page table\n");
294 shadow_cr3->pwt = new_cr3->pwt;
295 shadow_cr3->pcd = new_cr3->pcd;
298 *guest_cr3 = *new_cr3;
300 PrintDebug("New Shadow CR3=%x; New Guest CR3=%x\n",
301 *(uint_t*)shadow_cr3, *(uint_t*)guest_cr3);
303 if (info->mem_mode == VIRTUAL_MEM) {
304 // If we aren't in paged mode then we have to preserve the identity mapped CR3
305 info->ctrl_regs.cr3 = *(addr_t*)shadow_cr3;
309 PrintError("Unhandled opcode in handle_cr3_write\n");
313 info->rip += dec_instr.instr_length;
320 // first attempt = 156 lines
321 // current = 36 lines
322 int v3_handle_cr3_read(struct guest_info * info) {
325 struct x86_instr dec_instr;
327 if (info->mem_mode == PHYSICAL_MEM) {
328 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
330 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
333 /* The IFetch will already have faulted in the necessary bytes for the full instruction
335 // I think we should inject a GPF into the guest
336 PrintError("Could not read instruction (ret=%d)\n", ret);
341 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
342 PrintError("Could not decode instruction\n");
346 if (v3_opcode_cmp(V3_OPCODE_MOVCR2, (const uchar_t *)(dec_instr.opcode)) == 0) {
347 PrintDebug("MOVCR32\n");
348 struct cr3_32 * virt_cr3 = (struct cr3_32 *)(dec_instr.dst_operand.operand);
350 PrintDebug("CR3 at 0x%p\n", &(info->ctrl_regs.cr3));
352 if (info->shdw_pg_mode == SHADOW_PAGING) {
353 *virt_cr3 = *(struct cr3_32 *)&(info->shdw_pg_state.guest_cr3);
355 *virt_cr3 = *(struct cr3_32 *)&(info->ctrl_regs.cr3);
358 PrintError("Unhandled opcode in handle_cr3_read\n");
362 info->rip += dec_instr.instr_length;
367 int v3_handle_cr4_read(struct guest_info * info) {
368 PrintError("CR4 Read not handled\n");
372 int v3_handle_cr4_write(struct guest_info * info) {
375 struct x86_instr dec_instr;
377 if (info->mem_mode == PHYSICAL_MEM) {
378 ret = read_guest_pa_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
380 ret = read_guest_va_memory(info, get_addr_linear(info, info->rip, &(info->segments.cs)), 15, instr);
383 if (v3_decode(info, (addr_t)instr, &dec_instr) == -1) {
384 PrintError("Could not decode instruction\n");
388 if (v3_opcode_cmp(V3_OPCODE_MOV2CR, (const uchar_t *)(dec_instr.opcode)) != 0) {
389 PrintError("Invalid opcode in write to CR4\n");
393 if ((info->cpu_mode == PROTECTED) || (info->cpu_mode == PROTECTED_PAE)) {
394 struct cr4_32 * new_cr4 = (struct cr4_32 *)(dec_instr.src_operand.operand);
395 struct cr4_32 * old_cr4 = (struct cr4_32 *)&(info->ctrl_regs.cr4);
397 PrintDebug("OperandVal = %x, length = %d\n", *(uint_t *)new_cr4, dec_instr.src_operand.size);
398 PrintDebug("Old CR4=%x\n", *(uint_t *)old_cr4);
403 if ((info->shdw_pg_mode == SHADOW_PAGING) &&
404 (v3_get_mem_mode(info) == PHYSICAL_MEM)) {
406 if ((old_cr4->pae == 0) && (new_cr4->pae == 1)) {
407 PrintDebug("Creating PAE passthrough tables\n");
409 // Delete the old 32 bit direct map page tables
410 delete_page_tables_32((pde32_t *)V3_VAddr((void *)(info->direct_map_pt)));
412 // create 32 bit PAE direct map page table
413 info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_32PAE(info));
415 // reset cr3 to new page tables
416 info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
418 } else if ((old_cr4->pae == 1) && (new_cr4->pae == 0)) {
419 // Create passthrough standard 32bit pagetables
425 PrintDebug("New CR4=%x\n", *(uint_t *)old_cr4);
431 info->rip += dec_instr.instr_length;
436 int v3_handle_efer_read(uint_t msr, struct v3_msr * dst, void * priv_data) {
437 PrintError("EFER Read not handled\n");
442 int v3_handle_efer_write(uint_t msr, struct v3_msr src, void * priv_data) {
443 struct guest_info * info = (struct guest_info *)(priv_data);
444 struct efer_64 * new_efer = (struct efer_64 *)&(src.value);
445 struct efer_64 * old_efer = (struct efer_64 *)&(info->ctrl_regs.efer);
447 PrintDebug("Old EFER=%p\n", (void *)*(addr_t*)(old_efer));
449 if ((info->shdw_pg_mode == SHADOW_PAGING) &&
450 (v3_get_mem_mode(info) == PHYSICAL_MEM)) {
452 if ((old_efer->lme == 0) && (new_efer->lme == 1)) {
453 PrintDebug("Transition to longmode\n");
454 PrintDebug("Creating Passthrough 64 bit page tables\n");
456 // Delete the old 32 bit direct map page tables
459 * Will these page tables always be in PAE format??
461 PrintDebug("Deleting old PAE Page tables\n");
462 PrintError("JRL BUG?: Will the old page tables always be in PAE format??\n");
463 delete_page_tables_32PAE((pdpe32pae_t *)V3_VAddr((void *)(info->direct_map_pt)));
465 // create 64 bit direct map page table
466 info->direct_map_pt = (addr_t)V3_PAddr(create_passthrough_pts_64(info));
468 // reset cr3 to new page tables
469 info->ctrl_regs.cr3 = *(addr_t*)&(info->direct_map_pt);
472 // Does this mean we will have to fully virtualize a shadow EFER??
475 } else if ((old_efer->lme == 1) && (new_efer->lme == 0)) {
476 // transition out of long mode
480 *old_efer = *new_efer;
481 PrintDebug("New EFER=%p\n", (void *)*(addr_t *)(old_efer));
486 info->rip += 2; // WRMSR/RDMSR are two byte operands