There is a bug on get_be_long() that causes high 32 bits truncated.
As a result, we get wrong registers values from dump file. Patch 1
fixes this.
Once we can get right cpu registers values, it's better to use the
sp/ip for backtracing the active task. This can show a more accurate
backtrace, not including those invalid frames beyond sp. pathes 2 and
3 do this on kvmdump case(virsh dump).
To verify: run that km_probe.c test module on a x86_64 system, then
`echo q > /proc/sysrq-trigger' to trigger the kprobe which does
looping in post_handler. Then vrish dump then crash.
--
Thanks,
Hu Tao
diff --git a/qemu-load.c b/qemu-load.c
index 998b6d4..95eaf97 100644
--- a/qemu-load.c
+++ b/qemu-load.c
@@ -408,7 +408,7 @@ cpu_common_init_load (struct qemu_device_list *dl,
> Hi Dave,
>
> There is a bug on get_be_long() that causes high 32 bits truncated.
> As a result, we get wrong registers values from dump file. Patch 1
> fixes this.
Good catch!
> Once we can get right cpu registers values, it's better to use the
> sp/ip for backtracing the active task. This can show a more accurate
> backtrace, not including those invalid frames beyond sp. pathes 2 and
> 3 do this on kvmdump case(virsh dump).
>
> To verify: run that km_probe.c test module on a x86_64 system, then
> `echo q > /proc/sysrq-trigger' to trigger the kprobe which does
> looping in post_handler. Then vrish dump then crash.
However, I'm wondering whether you actually tested this with a
*crashed* system's dumpfile, and not just with a *live* system dump with
a contrived set of circumstances. And if so, what differences, if any,
did you see with the backtraces of the task that either oops'd or called
panic(), as well as those of the other active tasks that were brought down
by IP interrupt?
Anyway, I'll give this a thorough testing with a set of sample
dumpfiles that I have on hand.
Thanks,
Dave
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
> ----- "Hu Tao" <hutao@cn.fujitsu.com> wrote:
>
> > Hi Dave,
> >
> > There is a bug on get_be_long() that causes high 32 bits truncated.
> > As a result, we get wrong registers values from dump file. Patch 1
> > fixes this.
>
> Good catch!
>
> > Once we can get right cpu registers values, it's better to use the
> > sp/ip for backtracing the active task. This can show a more accurate
> > backtrace, not including those invalid frames beyond sp. pathes 2 and
> > 3 do this on kvmdump case(virsh dump).
> >
> > To verify: run that km_probe.c test module on a x86_64 system, then
> > `echo q > /proc/sysrq-trigger' to trigger the kprobe which does
> > looping in post_handler. Then vrish dump then crash.
>
> However, I'm wondering whether you actually tested this with a
> *crashed* system's dumpfile, and not just with a *live* system dump with
> a contrived set of circumstances. And if so, what differences, if any,
> did you see with the backtraces of the task that either oops'd or called
> panic(), as well as those of the other active tasks that were brought down
> by IP interrupt?
>
> Anyway, I'll give this a thorough testing with a set of sample
> dumpfiles that I have on hand.
Actually, the patch fails miserably on SMP dumpfiles with segmentation
during initialization.
And now looking at your patch, I'm wondering whether you even tested this
with an SMP system?
That function cycles through the "cpu" devices for *each* cpu
in the system, so this patch will store the device of the last cpu
device it encounters. So in an SMP machine, it will store the
device for the highest cpu only, right?
And then there's this change to get_kvmdump_regs():
is_task_active() returns TRUE for all active tasks in an SMP system,
not just the panic task. So it would seem you're going to pass
back the same registers for all active tasks?
Also, the change to main.c is unnecessary -- there are dozens of malloc'd
memory areas in the program -- so why go to the bother of free'ing
just this one prior to exiting?
Anyway, instead of saving the device list, I suggest you do something
like storing the per-cpu IP/SP values in a separate data structure that
can possibly be used as an alternative source for register values for
"live dumps" -- and possibly for crashing systems if usable starting
hooks cannot be determined in the traditional manner. I had thought
of doing something like that in the past, but when I looked at the
register values, I must have run into the get_be_long() issue?
Dave
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
10-19-2010, 12:36 AM
Hu Tao
bug on get_be_long() and improvement of bt
On Mon, Oct 18, 2010 at 09:56:41AM -0400, Dave Anderson wrote:
>
> ----- "Dave Anderson" <anderson@redhat.com> wrote:
>
> > ----- "Hu Tao" <hutao@cn.fujitsu.com> wrote:
> >
> > > Hi Dave,
> > >
> > > There is a bug on get_be_long() that causes high 32 bits truncated.
> > > As a result, we get wrong registers values from dump file. Patch 1
> > > fixes this.
> >
> > Good catch!
> >
> > > Once we can get right cpu registers values, it's better to use the
> > > sp/ip for backtracing the active task. This can show a more accurate
> > > backtrace, not including those invalid frames beyond sp. pathes 2 and
> > > 3 do this on kvmdump case(virsh dump).
> > >
> > > To verify: run that km_probe.c test module on a x86_64 system, then
> > > `echo q > /proc/sysrq-trigger' to trigger the kprobe which does
> > > looping in post_handler. Then vrish dump then crash.
> >
> > However, I'm wondering whether you actually tested this with a
> > *crashed* system's dumpfile, and not just with a *live* system dump with
> > a contrived set of circumstances. And if so, what differences, if any,
> > did you see with the backtraces of the task that either oops'd or called
> > panic(), as well as those of the other active tasks that were brought down
> > by IP interrupt?
> >
> > Anyway, I'll give this a thorough testing with a set of sample
> > dumpfiles that I have on hand.
>
> Actually, the patch fails miserably on SMP dumpfiles with segmentation
> during initialization.
>
> And now looking at your patch, I'm wondering whether you even tested this
> with an SMP system?
My fault. I will do more tests and improve the patch.
* test with a SMP system
* test with a live dump
* test with system panic/oops
* test with x86/x86_64
>
> The change to qemu_load() here:
>
> @@ -904,6 +906,9 @@ qemu_load (const struct qemu_device_loader *devices, uint32_t required_features,
> if (feof (fp) || ferror (fp))
> break;
>
> + if (STREQ(d->vtbl->name, "cpu"))
> + result->dx86 = d;
> +
> if (sec == QEMU_VM_SECTION_END || sec == QEMU_VM_SECTION_FULL)
> result->features |= features;
> }
>
> That function cycles through the "cpu" devices for *each* cpu
> in the system, so this patch will store the device of the last cpu
> device it encounters. So in an SMP machine, it will store the
> device for the highest cpu only, right?
>
> And then there's this change to get_kvmdump_regs():
>
> @@ -310,7 +311,11 @@ kvmdump_memory_dump(FILE *ofp)
> void
> get_kvmdump_regs(struct bt_info *bt, ulong *pc, ulong *sp)
> {
> - machdep->get_stack_frame(bt, pc, sp);
> + if (is_task_active(bt->task)) {
> + *sp = device_list->dx86->regs[R_ESP];
> + *pc = device_list->dx86->eip;
> + } else
> + machdep->get_stack_frame(bt, pc, sp);
> }
>
> is_task_active() returns TRUE for all active tasks in an SMP system,
> not just the panic task. So it would seem you're going to pass
> back the same registers for all active tasks?
>
> And what's the point of this change to kernel.c?
>
> diff --git a/kernel.c b/kernel.c
> index e399099..2627020 100755
> --- a/kernel.c
> +++ b/kernel.c
> @@ -16,6 +16,7 @@
> */
>
> #include "defs.h"
> +#include "qemu-load.h"
> #include "xen_hyper_defs.h"
> #include <elf.h>
>
> Also, the change to main.c is unnecessary -- there are dozens of malloc'd
> memory areas in the program -- so why go to the bother of free'ing
> just this one prior to exiting?
>
> Anyway, instead of saving the device list, I suggest you do something
> like storing the per-cpu IP/SP values in a separate data structure that
> can possibly be used as an alternative source for register values for
> "live dumps" -- and possibly for crashing systems if usable starting
> hooks cannot be determined in the traditional manner. I had thought
> of doing something like that in the past, but when I looked at the
> register values, I must have run into the get_be_long() issue?
Sounds reasonable. Thanks for suggestions.
--
Thanks,
Hu Tao
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
10-19-2010, 09:05 AM
Hu Tao
bug on get_be_long() and improvement of bt
Hi Dave,
These are updated patches tested with SMP system and panic task.
When testing a x86 guest, I found another bug about reading cpu
registers from dumpfile. Qemu simulated system is x86_64
(qemu-system-x86_64), guest OS is x86. When crash reads cpu registers
from dumpfile, it uses cpu_load_32(), this will read gp registers by
get_be_long(fp, 32), that is, treate them as 32bits. But in fact,
qemu-system-x86_64 saves 64bits for each of them(although guest OS
uses only lower 32 bits). As a result, crash gets wrong cpu gp
register values.
Is there any way we can know from dumpfile that these gp
registers(and those similar registers) are 32bits or 64bits?
--
Thanks,
Hu Tao
>From 007a86417ca1995e2727230851bd4f55dc8eff47 Mon Sep 17 00:00:00 2001
From: Hu Tao <hutao@cn.fujitsu.com>
Date: Mon, 18 Oct 2010 10:19:47 +0800
Subject: [PATCH 1/3] Return uint64_t for get_be_long()
>From de6809819c06cf8c294a03ad79207b3ac9c2dca8 Mon Sep 17 00:00:00 2001
From: Hu Tao <hutao@cn.fujitsu.com>
Date: Tue, 19 Oct 2010 13:10:12 +0800
Subject: [PATCH 3/3] Use cpu sp/ip to backtrace active task
-#include "defs.h"
-
int
is_qemu_vm_file(char *filename)
{
--
1.7.3
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
10-19-2010, 01:06 PM
Dave Anderson
bug on get_be_long() and improvement of bt
----- "Hu Tao" <hutao@cn.fujitsu.com> wrote:
> Hi Dave,
>
> These are updated patches tested with SMP system and panic task.
>
> When testing a x86 guest, I found another bug about reading cpu
> registers from dumpfile. Qemu simulated system is x86_64
> (qemu-system-x86_64), guest OS is x86. When crash reads cpu registers
> from dumpfile, it uses cpu_load_32(), this will read gp registers by
> get_be_long(fp, 32), that is, treate them as 32bits. But in fact,
> qemu-system-x86_64 saves 64bits for each of them(although guest OS
> uses only lower 32 bits). As a result, crash gets wrong cpu gp
> register values.
As I understand it, you're running a 32-bit guest on a 64-bit host.
If you were to read 64-bit register values instead of 32-bit register
values, wouldn't that cause the file offsets of the subsequent get_xxx()
calls in cpu_load() to read from the wrong file offsets? And then
that would leave the ending file offset incorrect, such that the
qemu_load() loop would fail to find the next device?
In other words, the cpu_load() function, which is used for both
32-bit and 64-bit guests, must be reading the correct amount of
data from the "cpu" device, or else qemu_load() would fail to
find the next device in the next location in the dumpfile.
> Is there any way we can know from dumpfile that these gp
> registers(and those similar registers) are 32bits or 64bits?
I don't know. If what you say is true, when would those registers
ever be 32-bit values?
Dave
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
10-20-2010, 05:38 AM
Hu Tao
bug on get_be_long() and improvement of bt
On Tue, Oct 19, 2010 at 09:06:33AM -0400, Dave Anderson wrote:
>
> ----- "Hu Tao" <hutao@cn.fujitsu.com> wrote:
>
> > Hi Dave,
> >
> > These are updated patches tested with SMP system and panic task.
> >
> > When testing a x86 guest, I found another bug about reading cpu
> > registers from dumpfile. Qemu simulated system is x86_64
> > (qemu-system-x86_64), guest OS is x86. When crash reads cpu registers
> > from dumpfile, it uses cpu_load_32(), this will read gp registers by
> > get_be_long(fp, 32), that is, treate them as 32bits. But in fact,
> > qemu-system-x86_64 saves 64bits for each of them(although guest OS
> > uses only lower 32 bits). As a result, crash gets wrong cpu gp
> > register values.
>
> As I understand it, you're running a 32-bit guest on a 64-bit host.
Yes.
> If you were to read 64-bit register values instead of 32-bit register
> values, wouldn't that cause the file offsets of the subsequent get_xxx()
> calls in cpu_load() to read from the wrong file offsets? And then
> that would leave the ending file offset incorrect, such that the
> qemu_load() loop would fail to find the next device?
>
> In other words, the cpu_load() function, which is used for both
> 32-bit and 64-bit guests, must be reading the correct amount of
> data from the "cpu" device, or else qemu_load() would fail to
> find the next device in the next location in the dumpfile.
True. In fact, in my case if read 32-bit registers, following devices
are found:
block, ram, kvm-tpr-opt, kvmclock, timer, cpu_common, cpu.
If read 64-bit registers, following devices are found:
block, ram, kvm-tpr-opt, kvmclock, timer, cpu_common, cpu, apic, fw_cfg
>
> > Is there any way we can know from dumpfile that these gp
> > registers(and those similar registers) are 32bits or 64bits?
>
> I don't know. If what you say is true, when would those registers
> ever be 32-bit values?
I did tests on a 64-bit machine. Result is:
machine OS guest machine guest OS saved gp regs
------------------------------------------------------------------------
64-bit x86 qemu-kvm(kvm enabled) x86 64 bits
64-bit x86 qemu(kvm disabled) x86 32 bits
I guess on a 32-bit machine saved gp regs shoule be 32bits, but I have no
32-bit machine to test.
--
Thanks,
Hu Tao
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
10-20-2010, 07:51 AM
Hu Tao
bug on get_be_long() and improvement of bt
And one more patch adding command `cpu' to show cpu registers.
--
Thanks,
Hu Tao
>From 3d737a7ea51261eb3d39febbcbf93cce02b458c1 Mon Sep 17 00:00:00 2001
From: Hu Tao <hutao@cn.fujitsu.com>
Date: Wed, 20 Oct 2010 15:40:07 +0800
Subject: [PATCH 4/4] Add a command cpu to show cpu registers
char *help_cpu[] = {
"cpu",
-"set context to the active task on a cpu",
-"[cpu]",
-" This command sets the current context to the active task on a cpu. If no",
-" argument is given, the current context is displayed.
",
-" cpu a valid cpu number
",
-" This command is not allowable on live systems.",
-"
EXAMPLES",
-" %s> cpu 1",
-" PID: 286",
-" COMMAND: "in.rlogind"",
-" TASK: c0b3a000 ",
-" CPU: 1 ",
-" STATE: TASK_RUNNING (ACTIVE)",
+"Show cpu registers",
NULL
};
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
10-20-2010, 01:00 PM
Dave Anderson
bug on get_be_long() and improvement of bt
----- "Hu Tao" <hutao@cn.fujitsu.com> wrote:
> And one more patch adding command `cpu' to show cpu registers.
I had considered a "regs" command in the past, but given that they
are not always available in the various dumpfiles, and if implemented
should be done for all architectures, and quite frankly they're often
not that interesting because in, say ELF core dumps, they're typically
redundantly displayed in the backtrace exception frame.
Since this is KVM-specific and x86/x86_64-specific, for now I will
fold your patch into "help -n", which dumps dumpfile-specific data.
We can revisit making it a new command if it can be made more
generally used.
Thanks,
Dave
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
10-20-2010, 01:11 PM
Dave Anderson
bug on get_be_long() and improvement of bt
----- "Hu Tao" <hutao@cn.fujitsu.com> wrote:
> On Tue, Oct 19, 2010 at 09:06:33AM -0400, Dave Anderson wrote:
> >
> > ----- "Hu Tao" <hutao@cn.fujitsu.com> wrote:
> >
> > > Hi Dave,
> > >
> > > These are updated patches tested with SMP system and panic
> task.
> > >
> > > When testing a x86 guest, I found another bug about reading cpu
> > > registers from dumpfile. Qemu simulated system is x86_64
> > > (qemu-system-x86_64), guest OS is x86. When crash reads cpu registers
> > > from dumpfile, it uses cpu_load_32(), this will read gp registers by
> > > get_be_long(fp, 32), that is, treate them as 32bits. But in fact,
> > > qemu-system-x86_64 saves 64bits for each of them(although guest OS
> > > uses only lower 32 bits). As a result, crash gets wrong cpu gp
> > > register values.
> >
> > As I understand it, you're running a 32-bit guest on a 64-bit host.
>
> Yes.
>
> > If you were to read 64-bit register values instead of 32-bit register
> > values, wouldn't that cause the file offsets of the subsequent get_xxx()
> > calls in cpu_load() to read from the wrong file offsets? And then
> > that would leave the ending file offset incorrect, such that the
> > qemu_load() loop would fail to find the next device?
> >
> > In other words, the cpu_load() function, which is used for both
> > 32-bit and 64-bit guests, must be reading the correct amount of
> > data from the "cpu" device, or else qemu_load() would fail to
> > find the next device in the next location in the dumpfile.
>
> True. In fact, in my case if read 32-bit registers, following devices
> are found:
> block, ram, kvm-tpr-opt, kvmclock, timer, cpu_common, cpu.
> If read 64-bit registers, following devices are found:
> block, ram, kvm-tpr-opt, kvmclock, timer, cpu_common, cpu, apic, fw_cfg
Right -- so it got "lost" after incorrectly gathering the data for the
first "cpu" device instance.
> > > Is there any way we can know from dumpfile that these gp
> > > registers(and those similar registers) are 32bits or 64bits?
> >
> > I don't know. If what you say is true, when would those registers
> > ever be 32-bit values?
>
> I did tests on a 64-bit machine. Result is:
>
> machine OS guest machine guest OS saved gp regs
> ------------------------------------------------------------------------
> 64-bit x86 qemu-kvm(kvm enabled) x86 64 bits
> 64-bit x86 qemu(kvm disabled) x86 32 bits
I don't understand what you mean when you say that the guest machine
is "kvm enabled" or "kvm disabled"?
And if your host machine is running a 32-bit x86 OS (on 64-bit hardware),
that's something I've never seen given that Red Hat only allows 64-bit
kernels as KVM hosts.
Dave
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility