diff options
author | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-11-18 21:08:15 +0000 |
---|---|---|
committer | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-11-18 21:08:15 +0000 |
commit | 01df040b52474b463d00fe908d5a14e1ecdc75bc (patch) | |
tree | 2d12dee18e87fae0438a76c4ae588a5f5a149eab /target-i386/op_helper.c | |
parent | 2dc9f4117c90c799bcdaacb3d29d2f0625bcc81c (diff) | |
download | hqemu-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.c | 46 |
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); |