X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_ctrl_regs.c;h=3616ae8a9b4ab972dd7584b3087ebcde8780fc71;hb=a7b07dc7f3bd9c28b0fbfb3c685a306326d56e76;hp=d5a86501460df091c609e07447d5782adc880902;hpb=1d5e0fcea2007c9f068cded1e98d17c80a306a19;p=palacios.git diff --git a/palacios/src/palacios/vmm_ctrl_regs.c b/palacios/src/palacios/vmm_ctrl_regs.c index d5a8650..3616ae8 100644 --- a/palacios/src/palacios/vmm_ctrl_regs.c +++ b/palacios/src/palacios/vmm_ctrl_regs.c @@ -557,28 +557,37 @@ int v3_handle_efer_read(struct guest_info * core, uint_t msr, struct v3_msr * ds } - -// TODO: this is a disaster we need to clean this up... int v3_handle_efer_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { - //struct efer_64 * new_efer = (struct efer_64 *)&(src.value); - struct efer_64 * shadow_efer = (struct efer_64 *)&(core->ctrl_regs.efer); - struct v3_msr * guest_efer = &(core->shdw_pg_state.guest_efer); + struct v3_msr * vm_efer = &(core->shdw_pg_state.guest_efer); + struct efer_64 * hw_efer = (struct efer_64 *)&(core->ctrl_regs.efer); + struct efer_64 old_hw_efer = *((struct efer_64 *)&core->ctrl_regs.efer); - PrintDebug("EFER Write\n"); - PrintDebug("EFER Write Values: HI=%x LO=%x\n", src.hi, src.lo); + PrintDebug("EFER Write HI=%x LO=%x\n", src.hi, src.lo); - //PrintDebug("Old EFER=%p\n", (void *)*(addr_t*)(shadow_efer)); - - // We virtualize the guests efer to hide the SVME and LMA bits - guest_efer->value = src.value; - - if (core->shdw_pg_mode == SHADOW_PAGING) { - // Enable/Disable Syscall - shadow_efer->sce = src.value & 0x1; - } else if (core->shdw_pg_mode == NESTED_PAGING) { - *(uint64_t *)shadow_efer = src.value; - shadow_efer->svme = 1; + // Set EFER value seen by guest if it reads EFER + vm_efer->value = src.value; + + // Set EFER value seen by hardware while the guest is running + *(uint64_t *)hw_efer = src.value; + + // Catch unsupported features + if ((old_hw_efer.lme == 1) && (hw_efer->lme == 0)) { + PrintError("Disabling long mode once it has been enabled is not supported\n"); + return -1; } + + // Set LME and LMA bits seen by hardware + if (old_hw_efer.lme == 0) { + // Long mode was not previously enabled, so the lme bit cannot + // be set yet. It will be set later when the guest sets CR0.PG + // to enable paging. + hw_efer->lme = 0; + } else { + // Long mode was previously enabled. Ensure LMA bit is set. + // VMX does not automatically set LMA, and this should not affect SVM. + hw_efer->lma = 1; + } + return 0; }