vmx realmode: Emulate MSR accesses.
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 31 Jan 2008 09:33:26 +0000 (09:33 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 31 Jan 2008 09:33:26 +0000 (09:33 +0000)
Signed-off-by: Nitin A Kamble <nitin.a.kamble@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/hvm/vmx/realmode.c
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/vmx/vmx.h

index b5952953c4b268031c049662c13644b5a4eff7a6..be74b85408481eb7d4776d7ca2ca1d828419ec3e 100644 (file)
@@ -410,6 +410,52 @@ realmode_write_cr(
     return X86EMUL_OKAY;
 }
 
+static int
+realmode_read_msr(
+    unsigned long reg,
+    uint64_t *val,
+    struct x86_emulate_ctxt *ctxt)
+{
+    struct cpu_user_regs _regs = { .ecx = (uint32_t)reg };
+
+    if ( !vmx_msr_read_intercept(&_regs) )
+    {
+        struct realmode_emulate_ctxt *rm_ctxt =
+            container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+        rm_ctxt->exn_vector = (uint8_t)__vmread(VM_ENTRY_INTR_INFO);
+        rm_ctxt->exn_insn_len = 0;
+        __vmwrite(VM_ENTRY_INTR_INFO, 0);
+        return X86EMUL_EXCEPTION;
+    }
+
+    *val = ((uint64_t)(uint32_t)_regs.edx << 32) || (uint32_t)_regs.eax;
+    return X86EMUL_OKAY;
+}
+
+static int
+realmode_write_msr(
+    unsigned long reg,
+    uint64_t val,
+    struct x86_emulate_ctxt *ctxt)
+{
+    struct cpu_user_regs _regs = {
+        .edx = (uint32_t)(val >> 32),
+        .eax = (uint32_t)val,
+        .ecx = (uint32_t)reg };
+
+    if ( !vmx_msr_write_intercept(&_regs) )
+    {
+        struct realmode_emulate_ctxt *rm_ctxt =
+            container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+        rm_ctxt->exn_vector = (uint8_t)__vmread(VM_ENTRY_INTR_INFO);
+        rm_ctxt->exn_insn_len = 0;
+        __vmwrite(VM_ENTRY_INTR_INFO, 0);
+        return X86EMUL_EXCEPTION;
+    }
+
+    return X86EMUL_OKAY;
+}
+
 static int realmode_write_rflags(
     unsigned long val,
     struct x86_emulate_ctxt *ctxt)
@@ -495,6 +541,8 @@ static struct x86_emulate_ops realmode_emulator_ops = {
     .write_io      = realmode_write_io,
     .read_cr       = realmode_read_cr,
     .write_cr      = realmode_write_cr,
+    .read_msr      = realmode_read_msr,
+    .write_msr     = realmode_write_msr,
     .write_rflags  = realmode_write_rflags,
     .wbinvd        = realmode_wbinvd,
     .cpuid         = realmode_cpuid,
index 7994af937d44af3db5d5d069665cdb4d0914996d..05dba0511636abc9a1727d1e1eb4be8611fc62a2 100644 (file)
@@ -2315,7 +2315,7 @@ static int is_last_branch_msr(u32 ecx)
     return 0;
 }
 
-static int vmx_do_msr_read(struct cpu_user_regs *regs)
+int vmx_msr_read_intercept(struct cpu_user_regs *regs)
 {
     u64 msr_content = 0;
     u32 ecx = regs->ecx, eax, edx;
@@ -2507,7 +2507,7 @@ extern bool_t mtrr_fix_range_msr_set(struct mtrr_state *v,
 extern bool_t mtrr_def_type_msr_set(struct mtrr_state *v, u64 msr_content);
 extern bool_t pat_msr_set(u64 *pat, u64 msr);
 
-static int vmx_do_msr_write(struct cpu_user_regs *regs)
+int vmx_msr_write_intercept(struct cpu_user_regs *regs)
 {
     u32 ecx = regs->ecx;
     u64 msr_content;
@@ -2949,12 +2949,12 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
         break;
     case EXIT_REASON_MSR_READ:
         inst_len = __get_instruction_length(); /* Safe: RDMSR */
-        if ( vmx_do_msr_read(regs) )
+        if ( vmx_msr_read_intercept(regs) )
             __update_guest_eip(inst_len);
         break;
     case EXIT_REASON_MSR_WRITE:
         inst_len = __get_instruction_length(); /* Safe: WRMSR */
-        if ( vmx_do_msr_write(regs) )
+        if ( vmx_msr_write_intercept(regs) )
             __update_guest_eip(inst_len);
         break;
 
index ec03e75d9c3a3f3ec40aaf7e8ec6dd90c7338220..f15975a09758bde34ac389915f0267ec7f2be20a 100644 (file)
@@ -37,6 +37,8 @@ void vmx_do_no_device_fault(void);
 void vmx_cpuid_intercept(
     unsigned int *eax, unsigned int *ebx,
     unsigned int *ecx, unsigned int *edx);
+int vmx_msr_read_intercept(struct cpu_user_regs *regs);
+int vmx_msr_write_intercept(struct cpu_user_regs *regs);
 void vmx_wbinvd_intercept(void);
 void vmx_realmode(struct cpu_user_regs *regs);
 int vmx_realmode_io_complete(void);