summaryrefslogtreecommitdiffstats
path: root/target-i386/op_helper.c
diff options
context:
space:
mode:
authoraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2008-11-18 21:08:15 +0000
committeraliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162>2008-11-18 21:08:15 +0000
commit01df040b52474b463d00fe908d5a14e1ecdc75bc (patch)
tree2d12dee18e87fae0438a76c4ae588a5f5a149eab /target-i386/op_helper.c
parent2dc9f4117c90c799bcdaacb3d29d2f0625bcc81c (diff)
downloadhqemu-01df040b52474b463d00fe908d5a14e1ecdc75bc.zip
hqemu-01df040b52474b463d00fe908d5a14e1ecdc75bc.tar.gz
x86: Debug register emulation (Jan Kiszka)
Built on top of previously enhanced breakpoint/watchpoint support, this patch adds full debug register emulation for the x86 architecture. Many corner cases were considered, and the result was successfully tested inside a Linux guest with gdb, but I won't be surprised if one or two scenarios still behave differently in reality. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5747 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-i386/op_helper.c')
-rw-r--r--target-i386/op_helper.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 90f685d..6dc0802 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -496,6 +496,17 @@ static void switch_tss(int tss_selector,
/* XXX: different exception if CALL ? */
raise_exception_err(EXCP0D_GPF, 0);
}
+
+#ifndef CONFIG_USER_ONLY
+ /* reset local breakpoints */
+ if (env->dr[7] & 0x55) {
+ for (i = 0; i < 4; i++) {
+ if (hw_breakpoint_enabled(env->dr[7], i) == 0x1)
+ hw_breakpoint_remove(env, i);
+ }
+ env->dr[7] &= ~0x55;
+ }
+#endif
}
/* check if Port I/O is allowed in TSS */
@@ -1879,8 +1890,11 @@ void helper_cmpxchg16b(target_ulong a0)
void helper_single_step(void)
{
- env->dr[6] |= 0x4000;
- raise_exception(EXCP01_SSTP);
+#ifndef CONFIG_USER_ONLY
+ check_hw_breakpoints(env, 1);
+ env->dr[6] |= DR6_BS;
+#endif
+ raise_exception(EXCP01_DB);
}
void helper_cpuid(void)
@@ -2868,6 +2882,10 @@ target_ulong helper_read_crN(int reg)
void helper_write_crN(int reg, target_ulong t0)
{
}
+
+void helper_movl_drN_T0(int reg, target_ulong t0)
+{
+}
#else
target_ulong helper_read_crN(int reg)
{
@@ -2913,6 +2931,24 @@ void helper_write_crN(int reg, target_ulong t0)
break;
}
}
+
+void helper_movl_drN_T0(int reg, target_ulong t0)
+{
+ int i;
+
+ if (reg < 4) {
+ hw_breakpoint_remove(env, reg);
+ env->dr[reg] = t0;
+ hw_breakpoint_insert(env, reg);
+ } else if (reg == 7) {
+ for (i = 0; i < 4; i++)
+ hw_breakpoint_remove(env, i);
+ env->dr[7] = t0;
+ for (i = 0; i < 4; i++)
+ hw_breakpoint_insert(env, i);
+ } else
+ env->dr[reg] = t0;
+}
#endif
void helper_lmsw(target_ulong t0)
@@ -2929,12 +2965,6 @@ void helper_clts(void)
env->hflags &= ~HF_TS_MASK;
}
-/* XXX: do more */
-void helper_movl_drN_T0(int reg, target_ulong t0)
-{
- env->dr[reg] = t0;
-}
-
void helper_invlpg(target_ulong addr)
{
helper_svm_check_intercept_param(SVM_EXIT_INVLPG, 0);
OpenPOWER on IntegriCloud