Hi Don,
This v2 version, plus the REMOTE_MEMSRC() patch below, is queued for
crash-7.0.4. How would you like the changelog message to read?
Tentatively I've got this:
- Resurrection of the remote analysis capability for use with the
"xen-crashd" daemon running on a Xen Dom0 host, which communicates
with a paused or shutdown DomU guest kernel. The daemon can be
accessed like so:
$ crash localhost:5991,/dev/xenmem vmlinux
(dslutz(a)verizon.com)
Thanks,
Dave
----- Original Message -----
On 11/19/13 14:28, Dave Anderson wrote:
>
> Hi Don,
>
> I still need some help understanding this "resurrection" of the remote
> access facility, i.e., the new meanings of the REMOTE_xxx flags/macros.
>
> The currently-existing comment for the is_remote_daemon() function
> in remote.c describes the (obsolete) usage of the facility:
>
> /*
> * Parse, verify and establish a connection with the network daemon
> * specified on the crash command line.
> *
> * The format is:
> [remote-hostname]:port[,remote-namelist][,remote-dumpfile]
> *
> * where everything but the port number is optional, and the
> remote-namelist
> * and remote-dumpfile can be reversed.
> *
> * 1. The default remote host is the local host.
> * 2. The default dumpfile is /dev/mem.
> * 3. If no remote-namelist and remote-dumpfile are given, the daemon
> * is queried for a kernel that matches the remote /proc/version.
> * If no local kernel namelist is entered, the remote version will
> * be copied locally when fd_init() is called.
> * 4. If a remote-dumpfile is given with no remote namelist, it is
> presumed
> * that the kernel namelist will be entered locally.
> */
>
> Back then, the remote "crashd" daemon could be contacted for:
>
> (1) live access to the remote machine's kernel using its /dev/mem, or
> (2) accessing a vmlinux/vmcore pair that existed on the remote machine.
>
> Can you explain this new usage? It sounds like there is a remote daemon
> running on a remote Dom0 kernel, and that your new functionality can only
> be used to:
>
> (1) access a running domU guest hosted by that remote system, or
> (2) access a paused domU guest hosted by that remote system.
>
> And that there is also a device that the the remote daemon uses
> to access the memory of the guest, be it paused or live.
>
> Am I in the ballpark?
Yes.
The currently proposed code for Dom0, does not support (1) mostly
because it seems much better to me to be able to poke around and look at
a fixed state of the domU.
There is a (3) in xen: guest has shutdown. A shutdown guest has
subtypes like "requested shutdown", "requested reboot",
"detected
crash", etc. Xen will set a guest in shutdown state when a double fault
or triple fault happens. A paused guest is the same as an unpaused
guest in shutdown state. Using a much older Xen, I known that that
version treated a double fault is the same as a reboot request. The bug
I was tracking down turned out to be a extra swapgs which will cause
many linux kernel's to double fault on a page fault.
I was also looking to be able to use old versions of crash so as to
make it easier to use and/or deploy. Since the 7.0.3 or older version of
crash only support "live access to the remote machine's kernel using its
/dev/mem "; I picked to default to be a paused system. Since crash
thinks the remote system is live, it keeps fetching state which is not
changing.
The "device that the the remote daemon uses ", is more a defined
ABI which has 2 layers libxl and libxc (what I all xc_* routines). In
this case I am using libxc calls. None of these require the guest to be
paused.
So it would not be hard to change the Xen code to support new
option (1) if there is need for such a mode. I could see adding some
sort of pause control as an extension to crash.
I have recently learn of another Xen tool: gdbsx. It is designed
to connect gdb to a running guest and pause and resume the guest on
demand. While I have not done very much with it, it looks to be
powerful. Since it is just gdb, it is missing crash's kernel support.
>
> Dave
While working on this email, I found out that it looks better to me to
include REMOTE_PAUSED() in REMOTE_MEMSRC(). I.E. either add the following:
From b4093734b2db8666f155032ffd9637dcfda0fc0b Mon Sep 17 00:00:00 2001
From: Don Slutz <dslutz(a)verizon.com>
Date: Wed, 20 Nov 2013 07:17:51 -0500
Subject: [PATCH] Add REMOTE_PAUSED() to REMOTE_MEMSRC()
And remove the redunent 'REMOTE_MEMSRC() || REMOTE_PAUSED()'.
Signed-off-by: Don Slutz <dslutz(a)verizon.com>
---
defs.h | 2 +-
memory.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index dae9662..2ec5540 100755
--- a/defs.h
+++ b/defs.h
@@ -254,7 +254,7 @@ struct number_option {
#define REMOTE_ACTIVE() (pc->flags & REM_LIVE_SYSTEM)
#define REMOTE_DUMPFILE() \
(pc->flags & (REM_NETDUMP|REM_MCLXCD|REM_LKCD|REM_S390D))
-#define REMOTE_MEMSRC() (REMOTE_ACTIVE() || REMOTE_DUMPFILE())
+#define REMOTE_MEMSRC() (REMOTE_ACTIVE() || REMOTE_PAUSED() ||
REMOTE_DUMPFILE())
#define LKCD_DUMPFILE() (pc->flags & (LKCD|REM_LKCD))
#define NETDUMP_DUMPFILE() (pc->flags & (NETDUMP|REM_NETDUMP))
#define DISKDUMP_DUMPFILE() (pc->flags & DISKDUMP)
diff --git a/memory.c b/memory.c
index cf8da2c..d17ba3c 100755
--- a/memory.c
+++ b/memory.c
@@ -14903,7 +14903,7 @@ memory_page_size(void)
if (machdep->pagesize)
return machdep->pagesize;
- if (REMOTE_MEMSRC() || REMOTE_PAUSED())
+ if (REMOTE_MEMSRC())
return remote_page_size();
switch (pc->flags & MEMORY_SOURCES)
--
1.7.11.7
or adjust patch v2 7/7 to also do this.
-Don Slutz
>
> ----- Original Message -----
>> On 11/19/13 11:08, Dave Anderson wrote:
>>> ----- Original Message -----
>>>> From: Don Slutz <dslutz(a)verizon.com>
>>>>
>>>> Currently crash 4.0 and later using the code:
>>>>
>>>>
http://lists.xen.org/archives/html/xen-devel/2013-11/msg02569.html
>>>>
>>>> There is some very limited documention on crashes remote ptotocol in:
>>>>
>>>>
http://lists.xen.org/archives/html/xen-devel/2013-11/msg02352.html
>>>>
>>>> and some fixes in the attachment
>>>> 0001-xen-crashd-Connect-crash-with-domain.patch
>>>> from the 1st link above.
>>>>
>>>> How ever there are issues with the current code:
>>>>
>>>> 1) The remote protocol has a minor issue (which I have not been able to
>>>> happen) based on the fact TCP/IP is stream based protocol. This
>>>> means
>>>> a RECV or a SEND may not do the fully requested size of data. In
>>>> fact
>>>> the current code assumes that the amount of data that a SEND is
>>>> called
>>>> with will all be read with a single RECV.
>>>>
>>>> 2) The most common mismatch between crash and older kernels is
>>>> phys_base. In the remote case, see if the remote server supports
>>>> vitrual memory access, and if so, see if phys_base can be
>>>> retreived.
>>>>
>>>> 3) crash assumes that the remote system is active and can not return
>>>> currect IP and SP to do a better back trace.
>>>>
>>>> 4) enable a non-active mode of remote access.
>>>>
>>>> This patch set attempts to fix these:
>>>>
>>>> The fix for #1 I have called NIL mode (patch 1).
>>>> The fix for #2 uses get_remote_phys_base (patch 3).
>>>> The fix for #3 uses get_remote_regs (patch 5).
>>>> The fix for #4 uses special file /dev/xenmem (patch 7).
>>>> It also REMOTE_NIL() to indicate "remote paused system".
>>>>
>>>> Don Slutz (7):
>>>> Add NIL mode to remote.
>>>> remote_proc_version: NULL terminate passed buffer on error.
>>>> Add get_remote_phys_base.
>>>> Add remote_vtop.
>>>> bt: get remote live registers if possible.
>>>> Add get_remote_cr3
>>>> Add support for non-live remote.
>>>>
>>>> defs.h | 8 +-
>>>> kernel.c | 25 +++-
>>>> memory.c | 25 +++-
>>>> remote.c | 462
>>>> +++++++++++++++++++++++++++++++++++++++++++++++++++++----------
>>>> x86_64.c | 24 ++++
>>>> 5 files changed, 465 insertions(+), 79 deletions(-)
>>>>
>>>> --
>>>> 1.8.4
>>>
>>> Hi Don,
>>>
>>> A few comments...
>>>
>>> I don't really understand what entity the code is communicating with,
>>> so for the most part, I'm primarily interested in making sure that your
>>> patches in no way can affect the normal usage of the crash utility.
>>>
>>> That being said, is the term "NIL mode" some kind of Xen-ism?
>> Nope, it is term I came up with to describe the protocol change.
>>> It wasn't
>>> until I saw the display_sys_stats() function that I even understood that
>>> REMOTE_NIL mean "(remote paused system)". Anyway, if you made it
>>> something
>>> like "REMOTE_PAUSED" or something like that, the code might make
some
>>> sense
>>> to the untrained eye.
>> Will do. Looking back at it, I ended up overloading the term. :(
>>> And it's not entirely clear to me what REMOTE_ACTIVE() means now? It
>>> used
>>> to imply communicating with a remote crash daeamon that accessed the live
>>> system that the daemon was running on. Has that meaning been changed to
>>> mean
>>> that crash is communicating with a daemon that's accessing a
"live" Xen
>>> guest
>>> kernel?
>> The meaning is not as clear. Since the existing versions of crash already
>> have REMOTE_ACTIVE() and I wanted the Xen utility to be usable to them, in
>> both cases the "live" Xen guest kernel is being accessed while it is
>> paused.
>> I added REMOTE_PAUSED() to have a few changes to crash to correctly
>> understand that the guest is paused. As part of this I add the fake file
>> "/dev/xenmem".
>>> I'm confused about these two changes, where you re-patch your own
patch:
>>>
>>> - else
>>> + else if (REMOTE_ACTIVE() && ((bt->task ==
tt->this_task) ||
>>> is_task_active(bt->task))) {
>>> + if (get_remote_regs(bt, &eip, &esp))
>>> + machdep->get_stack_frame(bt, &eip,
&esp);
>>> + } else
>>>
>>> followed by:
>>>
>>> - else if (REMOTE_ACTIVE() && ((bt->task ==
tt->this_task) ||
>>> is_task_active(bt->task))) {
>>> + else if (REMOTE_NIL() && ((bt->task == tt->this_task)
||
>>> is_task_active(bt->task))) {
>>> if (get_remote_regs(bt, &eip, &esp))
>>> machdep->get_stack_frame(bt, &eip,
&esp);
>>> } else
>> Clearly I need to adjust the patch order.
>>> If I'm not mistaken, it would seem to be impossible for
"(bt->task ==
>>> tt->this_task)"
>>> to ever be true in the REMOTE_NIL() case? As I recall tt->this_task
used
>>> to be the
>>> PID of the remote daemon itself, which would be accessing the memory of
>>> its
>>> own kernel.
>>> So how could the pid of the remote daemon ever be the target of a back
>>> trace of a
>>> paused guest? And so I don't understand why you first made an if
clause
>>> for
>>> REMOTE_ACTIVE() to begin with -- whatever that means now -- and then
>>> changed it to
>>> REMOTE_NIL()?
>> This came about from some old changes from 2012 to a crash version 4.0 for
>> other work. I had not thought of /dev/xenmem at the time, and just copied
>> the condition from above. I see no reason not to drop "bt->task ==
>> tt->this_task". Will check that the right actions are still done.
>>> In any case, since the ultimate change is only interested in
>>> REMOTE_NIL(),
>>> can you make it all less of an eyesore by encapulating its if case
>>> something like:
>>>
>>> else if (SADUMP_DUMPFILE())
>>> get_sadump_regs(bt, &eip, &esp);
>>> + else if (REMOTE_NIL()) {
>>> + if (!((bt->task == tt->this_task) ||
>>> is_task_active(bt->task)) ||
>>> + !get_remote_regs(bt, &eip, &esp))
>>> + machdep->get_stack_frame(bt, &eip,
&esp);
>>> } else
>>> machdep->get_stack_frame(bt, &eip, &esp);
>>>
>>> Note above, for consistency's sake with the rest of the crash utility,
>>> can you make get_remote_regs() return non-zero when it successfully gets
>>> the registers, and zero if it fails?
>> Sure.
>>> And lastly, can you fix these?
>>>
>>> $ make warn
>>> ...
>>> remote.c: In function ‘validate_phys_base’:
>>> remote.c:2302:25: warning: format ‘%llx’ expects argument of type
>>> ‘long long unsigned int’, but argument 3 has type ‘physaddr_t’
>>> [-Wformat]
>>> remote.c:2302:25: warning: format ‘%llx’ expects argument of type
>>> ‘long long unsigned int’, but argument 4 has type ‘physaddr_t’
>>> [-Wformat]
>>> remote.c:2302:25: warning: format ‘%llx’ expects argument of type
>>> ‘long long unsigned int’, but argument 5 has type ‘physaddr_t’
>>> [-Wformat]
>>> remote.c:2302:25: warning: format ‘%llx’ expects argument of type
>>> ‘long long unsigned int’, but argument 6 has type ‘physaddr_t’
>>> [-Wformat]
>>> remote.c: In function ‘remote_vtop’:
>>> remote.c:2361:2: warning: format ‘%llx’ expects argument of type
>>> ‘long long unsigned int’, but argument 4 has type ‘physaddr_t’
>>> [-Wformat]
>>> remote.c:2367:4: warning: format ‘%llx’ expects argument of type
>>> ‘long long unsigned int’, but argument 4 has type ‘physaddr_t’
>>> [-Wformat]
>>> remote.c:2352:18: warning: variable ‘p3’ set but not used
>>> [-Wunused-but-set-variable]
>>> remote.c:2352:13: warning: variable ‘p2’ set but not used
>>> [-Wunused-but-set-variable]
>>> remote.c:2352:8: warning: variable ‘p1’ set but not used
>>> [-Wunused-but-set-variable]
>>> remote.c: In function ‘get_remote_regs’:
>>> remote.c:2392:33: warning: unused variable ‘p6’ [-Wunused-variable]
>>> remote.c:2392:28: warning: variable ‘p5’ set but not used
>>> [-Wunused-but-set-variable]
>>> remote.c:2392:18: warning: variable ‘p3’ set but not used
>>> [-Wunused-but-set-variable]
>>> remote.c:2392:8: warning: variable ‘p1’ set but not used
>>> [-Wunused-but-set-variable]
>>> remote.c: In function ‘get_remote_cr3’:
>>> remote.c:2449:13: warning: variable ‘p2’ set but not used
>>> [-Wunused-but-set-variable]
>>> remote.c:2449:8: warning: variable ‘p1’ set but not used
>>> [-Wunused-but-set-variable]
>>> ...
>> Yes.
>>
>>> And I'm not interested in appending these to the 4 files that you
>>> changed:
>>>
>>> +/*
>>> + * Specify Emacs local variables so the formating
>>> + * of the code stays the same.
>>> + *
>>> + * Local variables:
>>> + * mode: C
>>> + * c-set-style: "BSD"
>>> + * c-basic-offset: 8
>>> + * indent-tabs-mode: t
>>> + * End:
>>> + */
>>>
>>> Thanks,
>>> Dave
>> Ok, that is 2 votes to drop this, so I will.
>> -Don Slutz
>>