Re: [RFC][PATCH 0/4] x86/entry: disallow #DB more

From: Peter Zijlstra
Date: Sat May 23 2020 - 09:02:43 EST


On Fri, May 22, 2020 at 03:13:57PM -0700, Andy Lutomirski wrote:
> On Fri, May 22, 2020 at 1:49 PM Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote:
> >
> > Hai, this kills #DB during NMI/#MC and with that allows removing all the nasty
> > IST rewrite crud.
> >
>
> This is great, except that the unconditional DR7 write is going to
> seriously hurt perf performance. Fortunately, no one cares about
> perf, right? :)

Good point, so the trivial optimization is below. I couldn't find
instruction latency numbers for DRn load/stores anywhere. I'm hoping
loads are cheap.

> Even just reading first won't help enough because DR7
> reads are likely to be VM exits.

WTF, why is virt always such a horrible piece of crap?

> Can we have a percpu dr7 shadow
> (with careful ordering) or even just a percpu count of dr7 users so we
> can skip this if there are no breakpoints? We have cpu_dr7, and some
> minor changes would make this work. Maybe replace all the direct
> cpu_dr7 access with helpers like dr7_set_bits() and dr7_clear_bits()?

I'll try and sort through that on Monday or so.


---
arch/x86/include/asm/debugreg.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

--- a/arch/x86/include/asm/debugreg.h
+++ b/arch/x86/include/asm/debugreg.h
@@ -97,7 +97,8 @@ extern void hw_breakpoint_restore(void);
static __always_inline void local_db_save(unsigned long *dr7)
{
get_debugreg(*dr7, 7);
- set_debugreg(0, 7);
+ if (*dr7)
+ set_debugreg(0, 7);
/*
* Ensure the compiler doesn't lower the above statements into
* the critical section; disabling breakpoints late would not
@@ -114,7 +115,8 @@ static __always_inline void local_db_res
* not be good.
*/
barrier();
- set_debugreg(dr7, 7);
+ if (dr7)
+ set_debugreg(dr7, 7);
}

#ifdef CONFIG_CPU_SUP_AMD