Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Feb 2014 15:48:12 +1100 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Justin Hibbits <jhibbits@freebsd.org>
Cc:        freebsd-bugs@freebsd.org, freebsd-gnats-submit@freebsd.org
Subject:   Re: misc/186699: ddb on i386 and amd64 should be enhanced to show MSR values (enhancement)
Message-ID:  <20140213143733.M930@besplex.bde.org>
In-Reply-To: <201402121807.s1CI73F3015439@cgiserv.freebsd.org>
References:  <201402121807.s1CI73F3015439@cgiserv.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20140213143733.M930>