Re: [RFC Patch 3/9] Modifying generic debug exception to use virtualdebug registers

From: Alan Stern
Date: Fri Oct 17 2008 - 11:55:55 EST


On Thu, 16 Oct 2008, Roland McGrath wrote:

> Ah, I now almost remember discussing this before. We went around with the
> notifier getting a pointer to "condition" to clear its bits, etc. So there
> is a special requirement for DIE_DEBUG notifiers to fiddle the vdr6 bits.
> That ought to be documented somewhere or other, as well as clearly
> commented in do_debug itself.
>
> And what does it mean exactly? The bits that should be left in thread.vdr6
> are the virtualized bits, not the raw hardware bits. That is, the low four
> bits might need to be reordered from the actual hardware order.
>
> And what about this scenario?
>
> 1. do_debug hits for %db3, being used for a ptrace user watchpoint
> -> vdr6 = hardware %db6 = 0x...08
> -> send SIGTRAP
> 2. do_debug hits for %db0, being used for an in-kernel hw_breakpoint
> -> hardware clears the low four bits before setting one of them
> -> vdr6 = hardware %db6 = 0x...01
> -> vdr6 &= ~1 = 0x...00
> -> run hw_breakpoint callback
> 3. try to return to user, deliver SIGTRAP to ptrace'ing debugger
> 4. debugger does PTRACE_PEEKUSR u_debugreg[6]
> -> read vdr6 = 0x...00
> -> wtf? where is my db3 hit?
>
> To get this scenario correct, the virtual db6 bits for ptrace need to
> remain set when there is a later do_debug that ptrace won't see.

I seem to recall doing some experiments to find out which bits in DR6
the CPU would set and which it would clear. According to the 386
manual the processor never clears any of the bits, but this was changed
in later models. And I seem to recall that the experiments showed that
gdb would not clear the bits either; it relied on the CPU to clear
them.

A kernel breakpoint shouldn't affect the task's virtualized view of
DR6. But only the hw-breakpoint notifier handler knows whether a
particular exception was caused by a kernel breakpoint. Conversely,
that handler knows _only_ about the 4 low-order bits in DR6; it can't
virtualize any of the other bits.

So this means that do_debug shouldn't modify the four low bits in vdr6.
Instead the hw-breakpoint handler should do whatever is needed to set
them properly: Leave them alone when a kernel breakpoint occurs,
otherwise clear them and set the bit corresponding to the user
breakpoint. In fact, the new ptrace_triggered() routine does set the
appropriate bit in vdr6.

I don't know how we should handle the BT (debug trap) and BS
(single-step exception) bits. Maybe the kprobes code can take care of
them.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/