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
This commit is contained in:
aliguori 2008-11-18 21:08:15 +00:00
parent 2dc9f4117c
commit 01df040b52
5 changed files with 217 additions and 42 deletions

View file

@ -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);