Hello Ken'ichi,
First let me say that I very much appreciate your looking into
this issue.
However, there is a problem with your patch such that it won't work
with the sample Fedora kernel that I was planning to use as a test case.
That kernel is this Fedora version:
Linux version 2.6.27-0.244.rc2.git1.fc10.x86_64
When I run with your patches, I still get the same initialization
time failure:
crash: cannot resolve: "end_pfn"
With the Fedora kernel, your changes to x86_64_init() are not executed because
the VM_2_6_11 flag does not get set here, but rather VM_XEN get set:
case PRE_GDB:
if (!(machdep->flags & VM_FLAGS)) {
if (symbol_exists("xen_start_info")) {
if (symbol_exists("low_pml4") &&
symbol_exists("swap_low_mappings"))
machdep->flags |= VM_XEN_RHEL4;
else
==============> machdep->flags |= VM_XEN;
} else if (symbol_exists("boot_vmalloc_pgt"))
machdep->flags |= VM_ORIG;
else
machdep->flags |= VM_2_6_11;
}
And that's because the Fedora kernel contains a "xen_start_info" symbol,
and so it presumes it's a xen kernel. Even if I force it to use
VM_2_6_11 with "--machdep vm=2.6.11" on the command line, it still
fails the same way in kernel_init() because, again, it thinks it's a xen
kernel:
if (symbol_exists("xen_start_info")) {
kt->flags |= ARCH_XEN;
if (!(kt->xen_flags & (SHADOW_PAGE_TABLES|CANONICAL_PAGE_TABLES)))
kt->xen_flags |= WRITABLE_PAGE_TABLES;
if (symbol_exists("phys_to_machine_mapping"))
get_symbol_data("phys_to_machine_mapping",
sizeof(ulong),
&kt->phys_to_machine_mapping);
else if (!(kt->xen_flags & CANONICAL_PAGE_TABLES)) {
kt->xen_flags &= ~WRITABLE_PAGE_TABLES;
kt->xen_flags |= SHADOW_PAGE_TABLES;
}
if (machine_type("X86"))
get_symbol_data("max_pfn", sizeof(ulong),
&kt->p2m_table_size);
if (machine_type("X86_64"))
===========> get_symbol_data("end_pfn", sizeof(ulong),
&kt->p2m_table_size);
if ((kt->m2p_page = (char *)malloc(PAGESIZE())) == NULL)
error(FATAL, "cannot malloc m2p page.");
}
I made a preliminary inquiry as to why a bare-metal kernel would have
a bunch of (unused) xen* symbols built into it, and as I understand it,
the pv_ops implementation allows for the same kernel (vmlinux) to be
used for bare-metal, or for xen/pv_ops, and for that matter kvm/pv_ops
and VMI/pv_ops (?).
Now, clearly the linux-2.6.27-rc5 vmlinux that you used for testing your
patch does *not* have the "xen_start_info" symbol contained in it, because
if it did, you would have run into the same problem as me. I'm guessing
that all of the xen symbols I seen in my kernel are due to a CONFIG-option
used by the Fedora kernel build? And perhaps the same thing is done for KVM?
(VMI?) By any chance, do you know exactly how the pv_ops implementations fit
together?
In any case, the benefit of the pv_ops implementation is supposed to be
the fact that the same vmlinux kernel can be used for bare-metal or virtualized
kernels, but it potentially makes things more difficult for the crash
utility. But given that the bare-metal/virualized kernels are identical, then
presumably the kernel's PAGE_OFFSET would be identical, and that's what your
patch
is addressing. However, crash will also need a way to determine whether
it's a xen kernel or not. For example, look at the crash sources for all
users of the XEN() macro.
So I'm thinking that there may have to be something like a new
virtualization_init() function called very early on that can determine
whether this kernel is a newer pv_ops kernel with xen, kvm, etc. possibly
built-in? So in your linux-2.6.27-rc5 vmlinux, the new function would see the
pv_ops symbols but no xen symbols, so it could set some "bare-metal" flag.
But in the Fedora kernel's case, it would see both pv_ops and xen symbols,
and then would have to actually read (if possible) the xen_start_info pointer
to see if it's been initialized to something -- hopefully without getting into
a chicken-and-egg situation. Worst case, it may require new crash command line
arguments such as --xen or --kvm. But I'm hoping to avoid that if at all possible.
Whatever gets done, it has the potential to be pretty ugly...
Do you have any thoughts on the matter?
Dave
----- "Ken'ichi Ohmichi" <oomichi(a)mxs.nes.nec.co.jp> wrote:
Hi,
Since linux-2.6.27 of x86_64, PAGE_OFFSET has been changed to
0xffff880000000000 from 0xffff810000000000.
This patch catches up this change.
I tested it on linux-2.6.27-rc5, and it works fine.
Thanks
Ken'ichi Ohmichi
Signed-off-by: Ken'ichi Ohmichi <oomichi(a)mxs.nes.nec.co.jp>
---
diff -rpuN crash-4.0-7.1.orig/defs.h crash-4.0-7.1/defs.h
--- crash-4.0-7.1.orig/defs.h 2008-09-01 20:19:06.000000000 +0900
+++ crash-4.0-7.1/defs.h 2008-09-01 20:22:07.000000000 +0900
@@ -2124,6 +2124,8 @@ struct load_module {
#define VMEMMAP_VADDR_2_6_24 0xffffe20000000000
#define VMEMMAP_END_2_6_24 0xffffe2ffffffffff
+#define PAGE_OFFSET_2_6_27 0xffff880000000000
+
#define USERSPACE_TOP_XEN 0x0000800000000000
#define PAGE_OFFSET_XEN 0xffff880000000000
#define VMALLOC_START_ADDR_XEN 0xffffc20000000000
diff -rpuN crash-4.0-7.1.orig/x86_64.c crash-4.0-7.1/x86_64.c
--- crash-4.0-7.1.orig/x86_64.c 2008-09-01 20:19:06.000000000 +0900
+++ crash-4.0-7.1/x86_64.c 2008-09-01 20:32:14.000000000 +0900
@@ -178,7 +178,6 @@ x86_64_init(int when)
case VM_2_6_11:
/* 2.6.11 layout */
machdep->machspec->userspace_top = USERSPACE_TOP_2_6_11;
- machdep->machspec->page_offset = PAGE_OFFSET_2_6_11;
machdep->machspec->vmalloc_start_addr =
VMALLOC_START_ADDR_2_6_11;
machdep->machspec->vmalloc_end = VMALLOC_END_2_6_11;
machdep->machspec->modules_vaddr = MODULES_VADDR_2_6_11;
@@ -190,6 +189,13 @@ x86_64_init(int when)
if (symbol_exists("vmemmap_populate"))
machdep->flags |= VMEMMAP;
+ if (symbol_exists("end_pfn"))
+ /* 2.6.11 layout */
+ machdep->machspec->page_offset = PAGE_OFFSET_2_6_11;
+ else
+ /* 2.6.27 layout */
+ machdep->machspec->page_offset = PAGE_OFFSET_2_6_27;
+
machdep->uvtop = x86_64_uvtop_level4;
break;
---