misc/186699: ddb on i386 and amd64 should be enhanced to show MSR values (enhancement)

Bruce Evans brde at optusnet.com.au
Thu Feb 13 05:20:02 UTC 2014


The following reply was made to PR misc/186699; it has been noted by GNATS.

From: Bruce Evans <brde at optusnet.com.au>
To: Justin Hibbits <jhibbits at freebsd.org>
Cc: freebsd-gnats-submit at freebsd.org, freebsd-bugs at freebsd.org
Subject: Re: misc/186699: ddb on i386 and amd64 should be enhanced to show
 MSR values (enhancement)
Date: Thu, 13 Feb 2014 15:48:12 +1100 (EST)

 On Wed, 12 Feb 2014, Justin Hibbits wrote:
 
 >> Description:
 > On x86 it would be very useful to be able to show MSR values using rdmsr in the debugger.
 
 All inline functions in <machine/cpufunc.h> should be backed by extern
 functions, as for <machine/atomic.h> on x86 (this too is broken on
 other arches).  This gives a function rdmsr() that can be called from
 the debugger, and many other functions, e.g., wrmsr().  On x86, this is
 currently misimplemented for just the inb() and outb() functions by
 hard-coding special cases for them.
 
 Special registers could also be supported directly by the debugger,
 but that is probably not needed for MSRs and it doesn't work so well.
 It doesn't automatically expand when access functions are added to
 <machine/cpufunc.h>.  It is hard to format the display of a potentially
 huge number of special registers nicely (the display is bad enough for
 just 8 general registers and a few others on i386, and broken with 16
 general registers on amd64 (*)).  It is difficult to support for
 external debuggers.  Special registers are just not returned for
 standard APIs like ptrace, so I think kdgb doesn't support them.  It
 could support them by hacking on the registers directly, but this is
 fragile.  Hacking on the registers directly is the same as you would
 do with rdmsr()/wrmsr() calls.  rdmsr() might return a wrong value
 because the value is changed while in debugger context.  wrmsr() might
 write corrupt the debugger context.
 
 (*) This was the bad display on i386 in FreeBSD-5:
 
 % db> sh re
 % cs                 0x8
 % ds                0x10
 % es                0x10
 % fs                0x18
 % ss          0xc0610010  scioctl+0xe90
 % eax               0x26
 % ecx         0xc0c14000
 % edx                  0
 % ebx                  0
 % esp         0xdb1e9c6c
 % ebp         0xdb1e9c6c
 % esi         0xc06f3140  main_console
 % edi         0xc06f7780  main_softc
 % eip         0xc0616331  Debugger+0x41
 % efl            0x80286
 % dr0                  0
 % dr1                  0
 % dr2                  0
 % dr3                  0
 % dr4         0xffff0ff0
 % dr5              0x400
 % dr6         0xffff0ff0
 % dr7              0x400
 % Debugger+0x41:  movl    $0,in_Debugger.0
 
 It is 24 lines long (not counting the prompt), so it barely avoids
 scrolling on 25-line terminals (it scrolls off the previous prompt and
 all context before that).  It wastes 8 lines for the rarely-interesting
 debug registers, although these registers are printed better by "sh
 wa" (the implementation makes them nontrivial to remove from the list
 in "sh re").  It uses 5 lines for segment registers, but these are
 rarely interesting, and %gs is missing.  Adding %gs would mess up the
 scrolling.  The ordering of registers is poor: %eax is in the middle
 where it is hardest to see; segment registers are not grouped with their
 associated general register or stack pointer.
 
 amd64 has 8 more registers, so scrolling on 25-line terminals is always
 broken for it.  amd64 omits the debug registers, but adds %gs and keeps
 printing all other segment registers, most of which are now completely
 uninteresting in long mode, so it needs to scroll by 1.  It actually
 needs to scroll by 2 or 3 since a line or 2 is needed for the more
 prompt.  i386 now omits the debug registers like amd64.
 
 Support for fpu/mmx/xmm/ymm/avx... registers is also missing.  These
 are rarely of interest in the kernel.  They are not supported by
 <machine/cpufunc.h>, so expanding that to externs wouldn't fix this.
 Userland debuggers have extensive decoding of these registers.  This
 is too heavyweight for a kernel debugger, and is still broken in gdb
 on amd64 for xmm registers (but works for xmm registers on i386 where
 it is less needed because xmm registers are not part of the ABI).
 
 Some other arches have many more than 8 or 16 general registers, so
 displaying them nicely is even more challenging.  Line-based output
 has some advantages, but is useless in interactive mode in the kernel
 since you can't grep it.  With 64-bit registers, it is difficult to
 fit even 2 registers on 1 line, or see the parts of the registers that
 you are interested in.
 
 I don't like the gdb register displays or gdb's handling of scrolling
 either.
 
 These display problems mean that if special registers are specially
 supported, they should not all be displayed at once.  There should be
 commands like "sh msr0".  These would only be slightly easier to type
 (and more than slightly less fragile) than "call rdmsr(0))".  The
 registers should then be usable in expressions too (e.g., $msr0).  The
 fix for the excessive display of debug registers in -current broke use
 of them in expressions ($dr0 works in FreeBSD-5 but not now).  More
 seriously, it also breaks setting them.
 
 Bruce


More information about the freebsd-bugs mailing list