Patchwork [v3,35/39] windbg: implement kd_api_read_msr and kd_api_write_msr

login
register
mail settings
Submitter Mihail Abakumov
Date Dec. 6, 2018, 12:01 p.m.
Message ID <154409771441.5432.1285340295550689902.stgit@Misha-PC.lan02.inno>
Download mbox | patch
Permalink /patch/674093/
State New
Headers show

Comments

Mihail Abakumov - Dec. 6, 2018, 12:01 p.m.
Add sub functions for helper_wrmsr and helper_rdmsr: cpu_x86_write_msr
and cpu_x86_read_msr.

Signed-off-by: Mikhail Abakumov <mikhail.abakumov@ispras.ru>
Signed-off-by: Pavel Dovgalyuk <dovgaluk@ispras.ru>
---
 include/exec/windbgstub-utils.h |    2 ++
 target/i386/cpu.h               |    5 +++++
 target/i386/misc_helper.c       |   39 ++++++++++++++++++++++++++++-----------
 target/i386/windbgstub.c        |   30 ++++++++++++++++++++++++++++++
 windbgstub.c                    |    8 ++++++++
 5 files changed, 73 insertions(+), 11 deletions(-)

Patch

diff --git a/include/exec/windbgstub-utils.h b/include/exec/windbgstub-utils.h
index adfc9936f3..74e3b9a0da 100644
--- a/include/exec/windbgstub-utils.h
+++ b/include/exec/windbgstub-utils.h
@@ -81,6 +81,8 @@  void kd_api_write_io_space(CPUState *cs, PacketData *pd);
 void kd_api_read_physical_memory(CPUState *cs, PacketData *pd);
 void kd_api_write_physical_memory(CPUState *cs, PacketData *pd);
 void kd_api_get_version(CPUState *cs, PacketData *pd);
+void kd_api_read_msr(CPUState *cs, PacketData *pd);
+void kd_api_write_msr(CPUState *cs, PacketData *pd);
 void kd_api_clear_all_internal_breakpoints(CPUState *cs, PacketData *pd);
 void kd_api_get_context_ex(CPUState *cs, PacketData *pd);
 void kd_api_set_context_ex(CPUState *cs, PacketData *pd);
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 9c52d0cbeb..0f451d81bf 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1680,6 +1680,11 @@  void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
 void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
 void cpu_x86_update_dr7(CPUX86State *env, uint32_t new_dr7);
 
+#ifndef CONFIG_USER_ONLY
+void cpu_x86_write_msr(CPUX86State *env, uint64_t val);
+uint64_t cpu_x86_read_msr(CPUX86State *env);
+#endif
+
 /* hw/pc.c */
 uint64_t cpu_get_tsc(CPUX86State *env);
 
diff --git a/target/i386/misc_helper.c b/target/i386/misc_helper.c
index 6ae67cf885..1f9adb246d 100644
--- a/target/i386/misc_helper.c
+++ b/target/i386/misc_helper.c
@@ -228,15 +228,8 @@  void helper_rdmsr(CPUX86State *env)
 {
 }
 #else
-void helper_wrmsr(CPUX86State *env)
+void cpu_x86_write_msr(CPUX86State *env, uint64_t val)
 {
-    uint64_t val;
-
-    cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
-
-    val = ((uint32_t)env->regs[R_EAX]) |
-        ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
-
     switch ((uint32_t)env->regs[R_ECX]) {
     case MSR_IA32_SYSENTER_CS:
         env->sysenter_cs = val & 0xffff;
@@ -386,11 +379,9 @@  void helper_wrmsr(CPUX86State *env)
         /* XXX: exception? */
         break;
     }
-
-    windbg_try_load();
 }
 
-void helper_rdmsr(CPUX86State *env)
+uint64_t cpu_x86_read_msr(CPUX86State *env)
 {
     uint64_t val;
 
@@ -537,6 +528,32 @@  void helper_rdmsr(CPUX86State *env)
         val = 0;
         break;
     }
+
+    return val;
+}
+
+void helper_wrmsr(CPUX86State *env)
+{
+    uint64_t val;
+
+    cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC());
+
+    val = ((uint32_t)env->regs[R_EAX]) |
+        ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32);
+
+    cpu_x86_write_msr(env, val);
+
+    windbg_try_load();
+}
+
+void helper_rdmsr(CPUX86State *env)
+{
+    uint64_t val;
+
+    cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 0, GETPC());
+
+    val = cpu_x86_read_msr(env);
+
     env->regs[R_EAX] = (uint32_t)(val);
     env->regs[R_EDX] = (uint32_t)(val >> 32);
 }
diff --git a/target/i386/windbgstub.c b/target/i386/windbgstub.c
index 9e84027f19..ccc7bc3035 100644
--- a/target/i386/windbgstub.c
+++ b/target/i386/windbgstub.c
@@ -1083,6 +1083,36 @@  void kd_api_set_context_ex(CPUState *cs, PacketData *pd)
     stl_p(&ctx->BytesCopied, len);
 }
 
+void kd_api_read_msr(CPUState *cs, PacketData *pd)
+{
+#ifndef CONFIG_USER_ONLY
+    DBGKD_READ_WRITE_MSR *m64c = &pd->m64.u.ReadWriteMsr;
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+    uint64_t val = cpu_x86_read_msr(env);
+
+    stq_p(&val, val);
+
+    m64c->DataValueLow = val;
+    m64c->DataValueHigh = val >> 32;
+    pd->m64.ReturnStatus = STATUS_SUCCESS;
+#endif /* !CONFIG_USER_ONLY */
+}
+
+void kd_api_write_msr(CPUState *cs, PacketData *pd)
+{
+#ifndef CONFIG_USER_ONLY
+    DBGKD_READ_WRITE_MSR *m64c = &pd->m64.u.ReadWriteMsr;
+    X86CPU *cpu = X86_CPU(cs);
+    CPUX86State *env = &cpu->env;
+    uint64_t val = m64c->DataValueLow | ((uint64_t) m64c->DataValueHigh) << 32;
+
+    cpu_x86_write_msr(env, ldq_p(&val));
+
+    pd->m64.ReturnStatus = STATUS_SUCCESS;
+#endif /* !CONFIG_USER_ONLY */
+}
+
 void kd_api_get_version(CPUState *cs, PacketData *pd)
 {
     DBGKD_GET_VERSION64 *kdver = (DBGKD_GET_VERSION64 *) (PTR(pd->m64) + 0x10);
diff --git a/windbgstub.c b/windbgstub.c
index 366856bc81..109a52b663 100644
--- a/windbgstub.c
+++ b/windbgstub.c
@@ -216,6 +216,14 @@  static void windbg_process_manipulate_packet(WindbgState *state)
         kd_api_get_version(cs, data);
         break;
 
+    case DbgKdReadMachineSpecificRegister:
+        kd_api_read_msr(cs, data);
+        break;
+
+    case DbgKdWriteMachineSpecificRegister:
+        kd_api_write_msr(cs, data);
+        break;
+
     case DbgKdClearAllInternalBreakpointsApi:
         kd_api_clear_all_internal_breakpoints(cs, data);
         return;