On Thu, Feb 27, 2025, Ravi Bangoria wrote: > > 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.) Actualy, I'll post this along with some other cleanups to the test, and a fix for Intel if needed (it _should_ pass on Intel). All the open-coded EFLAGS.TF literals can be replaced, and clobbering arithmetic flags with SS is really, really, gross. > --- > 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