> Somewhat related but independent: CPU automatically clears DEBUGCTL[BTF] > on #DB exception. So, when DEBUGCTL is save/restored by KVM (i.e. when > LBR virtualization is disabled), it's KVM's responsibility to clear > DEBUGCTL[BTF]. Found this with below KUT test. (I wasn't sure whether I should send a separate series for kernel fix + KUT patch, or you can squash kernel fix in your patch and I shall send only KUT patch. So for now, sending it as a reply here.) --- diff --git a/x86/debug.c b/x86/debug.c index f493567c..2d204c63 100644 --- a/x86/debug.c +++ b/x86/debug.c @@ -409,6 +409,45 @@ static noinline unsigned long singlestep_with_sti_hlt(void) return start_rip; } +static noinline unsigned long __run_basic_block_ss_test(void) +{ + unsigned long start_rip; + + wrmsr(MSR_IA32_DEBUGCTLMSR, DEBUGCTLMSR_BTF); + + asm volatile( + "pushf\n\t" + "pop %%rax\n\t" + "or $(1<<8),%%rax\n\t" + "push %%rax\n\t" + "popf\n\t" + "1: nop\n\t" + "jmp 2f\n\t" + "nop\n\t" + "2: lea 1b(%%rip), %0\n\t" + : "=r" (start_rip) : : "rax" + ); + + return start_rip; +} + +static void run_basic_block_ss_test(void) +{ + unsigned long jmp_target; + unsigned long debugctl; + + write_dr6(0); + jmp_target = __run_basic_block_ss_test() + 4; + + report(is_single_step_db(dr6[0]) && db_addr[0] == jmp_target, + "Basic Block Single-step #DB: 0x%lx == 0x%lx", db_addr[0], + jmp_target); + + debugctl = rdmsr(MSR_IA32_DEBUGCTLMSR); + /* CPU should automatically clear DEBUGCTL[BTF] on #DB exception */ + report(debugctl == 0, "DebugCtl[BTF] reset post #DB. 0x%lx", debugctl); +} + int main(int ac, char **av) { unsigned long cr4; @@ -475,6 +514,12 @@ int main(int ac, char **av) run_ss_db_test(singlestep_with_movss_blocking_and_dr7_gd); run_ss_db_test(singlestep_with_sti_hlt); + /* Seems DEBUGCTL[BTF] is not supported on Intel. Run it only on AMD */ + if (this_cpu_has(X86_FEATURE_SVM)) { + n = 0; + run_basic_block_ss_test(); + } + n = 0; write_dr1((void *)&value); write_dr6(DR6_BS); --- Thanks, Ravi