[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] handle x86_64 xen code/data relocation



Hi all,

Recent version of xen (ex. RHEL5.2, 3.2.0) on the x86_64
moves the physical(machine) address of xen code/data area after 
the system started up. The start address of this is stored in
'xen_phys_start'. Thus to get a machine address of a xen text symbol
from its virtual address, calculate 
"va - __XEN_VIRT_START +  xen_phys_start".

crash and makedumpfile command need the value of xen_phys_start.
They know the virtual address of 'xen_phys_start' symbol but
no way to extract the value of xen_phys_start.

I think adding the xen_phys_start value to the CRASHINFO ElfNote
section at first. (Plan A: patch for xen hypervisor code attaced)
It is smallest modification necessary over all.

On the other hand there is a opinion that it is better to upgrade
a user-package than a hypervisor or kernel package.
The xen_phys_start value can be got from /proc/iomem.
    -------------------------------------------------------
    # cat /proc/iomem
    ...
      7e600000-7f5fffff : Hypervisor code and data  *** this line
    ...
    -------------------------------------------------------
So the kexec-tools can handle it theoretically.

The Plan B is that kexec-tools adds another ElfNote section which
holds the xen_phys_start value. The attached patch works well
though I am concern about it is a bit tricky.

Which plan is better ?  Or more good implementation ?
Please comment.

(note that crash and makedumpfile modification is same degree
for both plan.)

Thanks.
Itsuro Oda

=== Plan A (modify the xen hypervisor. It is for RHEL5.2 but almost same for 
other version) ===
--- include/xen/elfcore.h.org   2008-04-17 14:11:41.000000000 +0900
+++ include/xen/elfcore.h       2008-04-17 14:11:57.000000000 +0900
@@ -66,6 +66,7 @@
     unsigned long xen_compile_time;
     unsigned long tainted;
 #ifdef CONFIG_X86
+    unsigned long xen_phys_start;
     unsigned long dom0_pfn_to_mfn_frame_list_list;
 #endif
 } crash_xen_info_t;
--- arch/x86/crash.c.org        2008-04-17 14:12:51.000000000 +0900
+++ arch/x86/crash.c    2008-04-17 14:13:13.000000000 +0900
@@ -102,6 +102,7 @@
     hvm_disable();
 
     info = kexec_crash_save_info();
+    info->xen_phys_start = xen_phys_start;
     info->dom0_pfn_to_mfn_frame_list_list =
         arch_get_pfn_to_mfn_frame_list_list(dom0);
 }
================================================================

=== Plan B (modify the kexec-tools. proof of concept version) ===
diff -ru kexec-tools-testing-20080324.org/kexec/arch/x86_64/crashdump-x86_64.c 
kexec-tools-testing-20080324/kexec/arch/x86_64/crashdump-x86_64.c
--- kexec-tools-testing-20080324.org/kexec/arch/x86_64/crashdump-x86_64.c       
2008-03-21 13:16:28.000000000 +0900
+++ kexec-tools-testing-20080324/kexec/arch/x86_64/crashdump-x86_64.c   
2008-04-22 15:15:08.000000000 +0900
@@ -73,6 +73,25 @@
        return -1;
 }
 
+static int get_hypervisor_paddr(struct kexec_info *info)
+{
+       uint64_t start;
+
+       if (!xen_present())
+               return 0;
+
+       if (parse_iomem_single("Hypervisor code and data\n", &start, NULL) == 
0) {
+               info->hypervisor_paddr_start = start;
+#ifdef DEBUG
+               printf("kernel load physical addr start = 0x%016Lx\n", start);
+#endif
+               return 0;
+       }
+
+       fprintf(stderr, "Cannot determine hypervisor physical load addr\n");
+       return -1;
+}
+
 /* Retrieve info regarding virtual address kernel has been compiled for and
  * size of the kernel from /proc/kcore. Current /proc/kcore parsing from
  * from kexec-tools fails because of malformed elf notes. A kernel patch has
@@ -581,6 +600,9 @@
        if (get_kernel_paddr(info))
                return -1;
 
+       if (get_hypervisor_paddr(info))
+               return -1;
+
        if (get_kernel_vaddr_and_size(info))
                return -1;
 
@@ -620,6 +642,9 @@
         */
        elfcorehdr = add_buffer(info, tmp, sz, 16*1024, align, min_base,
                                                        max_addr, -1);
+       if (info->hypervisor_paddr_start && xen_present()) {
+               *(info->hypervisor_paddr_loc) += elfcorehdr;
+       }
        if (delete_memmap(memmap_p, elfcorehdr, sz) < 0)
                return -1;
        cmdline_add_memmap(mod_cmdline, memmap_p);
diff -ru kexec-tools-testing-20080324.org/kexec/crashdump.c 
kexec-tools-testing-20080324/kexec/crashdump.c
--- kexec-tools-testing-20080324.org/kexec/crashdump.c  2008-03-21 
13:16:28.000000000 +0900
+++ kexec-tools-testing-20080324/kexec/crashdump.c      2008-04-22 
15:33:47.000000000 +0900
@@ -36,8 +36,10 @@
 #define FUNC crash_create_elf64_headers
 #define EHDR Elf64_Ehdr
 #define PHDR Elf64_Phdr
+#define NHDR Elf64_Nhdr
 #include "crashdump-elf.c"
 #undef ELF_WIDTH
+#undef NHDR
 #undef PHDR
 #undef EHDR
 #undef FUNC
@@ -46,8 +48,10 @@
 #define FUNC crash_create_elf32_headers
 #define EHDR Elf32_Ehdr
 #define PHDR Elf32_Phdr
+#define NHDR Elf32_Nhdr
 #include "crashdump-elf.c"
 #undef ELF_WIDTH
+#undef NHDR
 #undef PHDR
 #undef EHDR
 #undef FUNC
diff -ru kexec-tools-testing-20080324.org/kexec/crashdump-elf.c 
kexec-tools-testing-20080324/kexec/crashdump-elf.c
--- kexec-tools-testing-20080324.org/kexec/crashdump-elf.c      2008-01-11 
12:13:48.000000000 +0900
+++ kexec-tools-testing-20080324/kexec/crashdump-elf.c  2008-04-22 
15:35:16.000000000 +0900
@@ -1,6 +1,6 @@
 
-#if !defined(FUNC) || !defined(EHDR) || !defined(PHDR)
-#error FUNC, EHDR and PHDR must be defined
+#if !defined(FUNC) || !defined(EHDR) || !defined(PHDR) || !defined(NHDR)
+#error FUNC, EHDR, PHDR and NHDR must be defined
 #endif
 
 #if (ELF_WIDTH == 64)
@@ -37,6 +37,7 @@
        uint64_t vmcoreinfo_addr, vmcoreinfo_len;
        int has_vmcoreinfo = 0;
        int (*get_note_info)(int cpu, uint64_t *addr, uint64_t *len);
+       int has_hypervisor_paddr_start = 0;
 
        if (xen_present())
                nr_cpus = xen_get_nr_phys_cpus();
@@ -78,6 +79,11 @@
                sz += sizeof(PHDR);
        }
 
+       if (info->hypervisor_paddr_start && xen_present()) {
+               sz += sizeof(PHDR) + sizeof(NHDR) + 4 + sizeof(unsigned long);
+               has_hypervisor_paddr_start = 1;
+       }
+
        /*
         * Make sure the ELF core header is aligned to at least 1024.
         * We do this because the secondary kernel gets the ELF core
@@ -168,6 +174,22 @@
                dbgprintf_phdr("vmcoreinfo header", phdr);
        }
 
+       if (has_hypervisor_paddr_start) {
+               phdr = (PHDR *) bufp;
+               bufp += sizeof(PHDR);
+               phdr->p_type    = PT_NOTE;
+               phdr->p_flags   = 0;
+               phdr->p_offset  = phdr->p_paddr = 0;
+               phdr->p_vaddr   = 0;
+               phdr->p_filesz  = phdr->p_memsz = sizeof(NHDR) + 4 + 
sizeof(unsigned long);
+               phdr->p_align   = 0;
+
+               (elf->e_phnum)++;
+               dbgprintf_phdr("hypervisor phys addr header", phdr);
+
+               info->hypervisor_paddr_loc = (unsigned long *)&phdr->p_offset;
+       }
+
        /* Setup an PT_LOAD type program header for the region where
         * Kernel is mapped if info->kern_size is non-zero.
         */
@@ -225,6 +247,24 @@
                (elf->e_phnum)++;
                dbgprintf_phdr("Elf header", phdr);
        }
+
+       if (has_hypervisor_paddr_start) {
+               NHDR *nhdr;
+               unsigned int offset = (void *)bufp - *buf;
+
+               nhdr = (NHDR *) bufp;
+               bufp += sizeof(NHDR);
+               nhdr->n_namesz = 4;
+               nhdr->n_descsz = sizeof(unsigned long);
+               nhdr->n_type = 0x1000003;
+               memcpy(bufp, "Xen", 4);
+               bufp += 4;
+               *((unsigned long *)bufp) = info->hypervisor_paddr_start;
+               bufp += sizeof(unsigned long);
+
+               *(info->hypervisor_paddr_loc) = offset;
+       }
+
        return 0;
 }
 
diff -ru kexec-tools-testing-20080324.org/kexec/kexec.h 
kexec-tools-testing-20080324/kexec/kexec.h
--- kexec-tools-testing-20080324.org/kexec/kexec.h      2008-03-21 
13:16:28.000000000 +0900
+++ kexec-tools-testing-20080324/kexec/kexec.h  2008-04-22 15:08:57.000000000 
+0900
@@ -123,6 +123,8 @@
        unsigned long kern_vaddr_start;
        unsigned long kern_paddr_start;
        unsigned long kern_size;
+       unsigned long hypervisor_paddr_start;
+       unsigned long *hypervisor_paddr_loc;
 };
 
 void usage(void);
======================================================================================
-- 
Itsuro ODA <oda@xxxxxxxxxxxxx>


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.