Hi, I sent the following e-mail to kexec-mailing list (kexec@lists.infradead.org) since subjects of makedumpfile are discussed on the mailing list. I want to inform this to xen developers since I think this function is useful for xen developers. Thanks. Itsuro Oda (see https://sourceforge.net/projects/makedumpfile/ about makedumpfile command.) Forwarded by Itsuro ODA <oda@valinux.co.jp> ----------------------- Original Message ----------------------- From: Itsuro ODA <oda@valinux.co.jp> To: kexec@lists.infradead.org Cc: oomichi@mxs.nes.nec.co.jp Date: Mon, 28 May 2007 10:49:49 +0900 Subject: [RFC] makedumpfile: xen extraction ---- Hi, I think the part of xen hypervisor and domain-0 is enough to analyze a cause of system crash in almost of all cases under xen environment. Thus extracting the part of xen and domain-0 from /proc/vmcore under the second kernel is useful to reduce down time. The attached patch enables makedumpfile to extract the part of xen and domain-0 from vmcore. I implemented this function as an option of makedumpfile since many parts of makedumpfile can be used for implement of this function and the aim of this function is same as the aim of makedumpfile. usage: -X option is added for this funtion. -E and "-x xen-syms" must be specified with -X. "makedumpfile -XE -x xen-syms [-D] vmcore output-vmcore" This patch is for makedumpfile-1.1.3. This patch supports x86-PAE and ia64 now. (x86 and x86_64 is easy to support. I''d like to get feedbacks before implement many architectures.) The output-vmcore can be analyzed by "crash" command for both of xen hypervisor and domain-0. Your comments are welcome. Thanks. Itsuro Oda ------------------------------------------------------------------------------- Index: Makefile ==================================================================RCS file: /cvsroot/xen_ia64/people/oda/makedumpfile-1.1.3/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Makefile 26 Apr 2007 02:32:30 -0000 1.1 +++ Makefile 16 May 2007 04:09:39 -0000 1.2 @@ -6,7 +6,7 @@ CC = gcc CFLAGS = -g -O2 -Wall -D_FILE_OFFSET_BITS=64 \ -DVERSION=''"$(VERSION)"'' -DRELEASE_DATE=''"$(DATE)"'' -CFLAGS_ARCH = -g -O2 -Wall +CFLAGS_ARCH = -g -O2 -Wall -D_FILE_OFFSET_BITS=64 ARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/sun4u/sparc64/ \ -e s/arm.*/arm/ -e s/sa110/arm/ \ Index: ia64.c ==================================================================RCS file: /cvsroot/xen_ia64/people/oda/makedumpfile-1.1.3/ia64.c,v retrieving revision 1.1 retrieving revision 1.6 diff -u -r1.1 -r1.6 --- ia64.c 26 Apr 2007 02:32:30 -0000 1.1 +++ ia64.c 27 May 2007 23:46:07 -0000 1.6 @@ -48,5 +48,94 @@ return TRUE; } +/* + * for Xen extraction + */ +unsigned long long +kvtop_xen_ia64(struct DumpInfo *info, unsigned long kvaddr) +{ + unsigned long long addr, dirp, entry; + + if (!is_xen_vaddr(kvaddr)) + return 0; + + if (is_direct(kvaddr)) + return (unsigned long)kvaddr - DIRECTMAP_VIRT_START; + + if (!is_frame_table_vaddr(kvaddr)) + return 0; + + addr = kvaddr - VIRT_FRAME_TABLE_ADDR; + + dirp = SYMBOL(frametable_pg_dir) - DIRECTMAP_VIRT_START; + dirp += ((addr >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) * sizeof(unsigned long long); + if (!readpmem(info, dirp, &entry, sizeof(entry))) + return FALSE; + + dirp = entry & _PFN_MASK; + if (!dirp) + return 0; + dirp += ((addr >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) * sizeof(unsigned long long); + if (!readpmem(info, dirp, &entry, sizeof(entry))) + return FALSE; + + dirp = entry & _PFN_MASK; + if (!dirp) + return 0; + dirp += ((addr >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) * sizeof(unsigned long long); + if (!readpmem(info, dirp, &entry, sizeof(entry))) + return FALSE; + + if (!(entry & _PAGE_P)) + return 0; + + entry = (entry & _PFN_MASK) + (addr & ((1UL << PAGESHIFT()) - 1)); + + return entry; +} + +int +get_xen_info_ia64(struct DumpInfo *info) +{ + unsigned long xen_start, xen_end, xen_heap_start; + int i; + + info->frame_table_vaddr = VIRT_FRAME_TABLE_ADDR; /* "frame_table" is same value */ + + if (SYMBOL(xenheap_phys_end) == NOT_FOUND_SYMBOL) { + ERRMSG("Can''t get the symbol of xenheap_phys_end.\n"); + return FALSE; + } + if (!readmem_xen(info, SYMBOL(xenheap_phys_end), &xen_end, + sizeof(xen_end), "Can''t get the value of xenheap_phys_end.\n")) + return FALSE; + + if (SYMBOL(xen_pstart) == NOT_FOUND_SYMBOL) { + ERRMSG("Can''t get the symbol of xen_pstart.\n"); + return FALSE; + } + if (!readmem_xen(info, SYMBOL(xen_pstart), &xen_start, + sizeof(xen_start), "Can''t get the value of xen_pstart.\n")) + return FALSE; + + info->xen_heap_end = (xen_end >> PAGESHIFT()); + info->xen_heap_start = (xen_start >> PAGESHIFT()); + + if (SYMBOL(xen_heap_start) == NOT_FOUND_SYMBOL) { + ERRMSG("Can''t get the symbol of xen_heap_start.\n"); + return FALSE; + } + if (!readmem_xen(info, SYMBOL(xen_heap_start), &xen_heap_start, + sizeof(xen_heap_start), "Can''t get the value of xen_heap_start.\n")) + return FALSE; + + for (i = 0; i < info->num_domain; i++) { + info->domain_list[i].pickled_id = (unsigned int) + (info->domain_list[i].domain_addr - xen_heap_start); + } + + return TRUE; +} + #endif /* ia64 */ Index: makedumpfile.c ==================================================================RCS file: /cvsroot/xen_ia64/people/oda/makedumpfile-1.1.3/makedumpfile.c,v retrieving revision 1.1 retrieving revision 1.14 diff -u -r1.1 -r1.14 --- makedumpfile.c 26 Apr 2007 02:32:30 -0000 1.1 +++ makedumpfile.c 27 May 2007 23:46:07 -0000 1.14 @@ -108,6 +108,36 @@ } int +readpmem(struct DumpInfo *info, unsigned long long paddr, void *bufptr, + size_t size) +{ + off_t offset; + const off_t failed = (off_t)-1; + + /* + * Convert Physical Address to File Offset. + */ + if (!(offset = paddr_to_offset(info, paddr))) { + ERRMSG("Can''t convert a physical address(%llx) to offset.\n", + paddr); + return FALSE; + } + if (lseek(info->fd_memory, offset, SEEK_SET) == failed) { + ERRMSG("Can''t seek the dump memory(%s). %s\n", + info->name_memory, strerror(errno)); + return FALSE; + } + + if (read(info->fd_memory, bufptr, size) != size) { + ERRMSG("Can''t read the dump memory(%s). %s\n", + info->name_memory, strerror(errno)); + return FALSE; + } + + return size; +} + +int readmem(struct DumpInfo *info, unsigned long long vaddr, void *bufptr, size_t size) { @@ -4132,6 +4162,395 @@ return TRUE; } +/* + * for Xen extraction + */ +int +get_symbol_info_xen(struct DumpInfo *info) +{ + /* common symbol */ + SYMBOL_INIT(dom_xen, "dom_xen"); + SYMBOL_INIT(dom_io, "dom_io"); + SYMBOL_INIT(domain_list, "domain_list"); + SYMBOL_INIT(frame_table, "frame_table"); + SYMBOL_INIT(alloc_bitmap, "alloc_bitmap"); + SYMBOL_INIT(max_page, "max_page"); + SYMBOL_INIT(xenheap_phys_end, "xenheap_phys_end"); + + /* architecture specific */ + SYMBOL_INIT(pgd_l2, "idle_pg_table_l2"); /* x86 */ + SYMBOL_INIT(pgd_l3, "idle_pg_table_l3"); /* x86-PAE */ + SYMBOL_INIT(pgd_l4, "idle_pg_table_4"); /* x86_64 */ + SYMBOL_INIT(xen_heap_start, "xen_heap_start"); /* ia64 */ + SYMBOL_INIT(xen_pstart, "xen_pstart"); /* ia64 */ + SYMBOL_INIT(frametable_pg_dir, "frametable_pg_dir"); /* ia64 */ + + return TRUE; +} + +int +get_structure_info_xen(struct DumpInfo *info) +{ + SIZE_INIT(page_info, "page_info"); + OFFSET_INIT(page_info.count_info, "page_info", "count_info"); + /* _domain is the first member of union u */ + OFFSET_INIT(page_info._domain, "page_info", "u"); + + SIZE_INIT(domain, "domain"); + OFFSET_INIT(domain.domain_id, "domain", "domain_id"); + OFFSET_INIT(domain.next_in_list, "domain", "next_in_list"); + + return TRUE; +} + +int +readmem_xen(struct DumpInfo *info, unsigned long long vaddr, void *bufptr, + size_t size, char *errmsg) +{ + unsigned long long paddr; + + if (!(paddr = kvtop_xen(info, vaddr))) + goto out; + + if (!readpmem(info, paddr, bufptr, size)) + goto out; + + return size; +out: + if (errmsg) + ERRMSG(errmsg); + + return 0; +} + +int +get_xen_info(struct DumpInfo *info) +{ + unsigned long domain; + unsigned int domain_id; + int num_domain; + + if (SYMBOL(alloc_bitmap) == NOT_FOUND_SYMBOL) { + ERRMSG("Can''t get the symbol of alloc_bitmap.\n"); + return FALSE; + } + if (!readmem_xen(info, SYMBOL(alloc_bitmap), &info->alloc_bitmap, + sizeof(info->alloc_bitmap), "Can''t get the value of alloc_bitmap.\n")) + return FALSE; + + if (SYMBOL(max_page) == NOT_FOUND_SYMBOL) { + ERRMSG("Can''t get the symbol of max_page.\n"); + return FALSE; + } + if (!readmem_xen(info, SYMBOL(max_page), &info->max_page, + sizeof(info->max_page), "Can''t get the value of max_page.\n")) + return FALSE; + + /* walk through domain_list */ + if (SYMBOL(domain_list) == NOT_FOUND_SYMBOL) { + ERRMSG("Can''t get the symbol of domain_list.\n"); + return FALSE; + } + if (!readmem_xen(info, SYMBOL(domain_list), &domain, + sizeof(domain), "Can''t get the value of domain_list.\n")) + return FALSE; + + /* get numbers of domain first */ + num_domain = 0; + while (domain) { + num_domain++; + if (!readmem_xen(info, domain + OFFSET(domain.next_in_list), + &domain, sizeof(domain), + "Can''t get through the domain_list.\n")) + return FALSE; + } + + if ((info->domain_list = (struct domain_list *) + malloc(sizeof(struct domain_list) * (num_domain + 2))) == NULL) { + ERRMSG("Can''t allcate memory for domain_list.\n"); + return FALSE; + } + + info->num_domain = num_domain + 2; + + if (!readmem_xen(info, SYMBOL(domain_list), &domain, + sizeof(domain), "Can''t get the value of domain_list.\n")) + return FALSE; + + num_domain = 0; + while (domain) { + if (!readmem_xen(info, domain + OFFSET(domain.domain_id), + &domain_id, sizeof(domain_id), + "Can''t get the domain_id.\n")) + return FALSE; + info->domain_list[num_domain].domain_addr = domain; + info->domain_list[num_domain].domain_id = domain_id; + /* pickled_id is set by architecture specific */ + num_domain++; + + if (!readmem_xen(info, domain + OFFSET(domain.next_in_list), + &domain, sizeof(domain), + "Can''t get through the domain_list.\n")) + return FALSE; + } + + /* special domains */ + if (SYMBOL(dom_xen) == NOT_FOUND_SYMBOL) { + ERRMSG("Can''t get the symbol of dom_xen.\n"); + return FALSE; + } + if (!readmem_xen(info, SYMBOL(dom_xen), &domain, sizeof(domain), + "Can''t get the value of dom_xen.\n")) + return FALSE; + if (!readmem_xen(info, domain + OFFSET(domain.domain_id), &domain_id, + sizeof(domain_id), "Can''t get the value of dom_xen domain_id.\n")) + return FALSE; + info->domain_list[num_domain].domain_addr = domain; + info->domain_list[num_domain].domain_id = domain_id; + num_domain++; + + if (SYMBOL(dom_io) == NOT_FOUND_SYMBOL) { + ERRMSG("Can''t get the symbol of dom_io.\n"); + return FALSE; + } + if (!readmem_xen(info, SYMBOL(dom_io), &domain, sizeof(domain), + "Can''t get the value of dom_io.\n")) + return FALSE; + if (!readmem_xen(info, domain + OFFSET(domain.domain_id), &domain_id, + sizeof(domain_id), "Can''t get the value of dom_io domain_id.\n")) + return FALSE; + info->domain_list[num_domain].domain_addr = domain; + info->domain_list[num_domain].domain_id = domain_id; + + /* get architecture specific data */ + if (!get_xen_info_arch(info)) + return FALSE; + + return TRUE; +} + +void +show_data_xen(struct DumpInfo *info) +{ + int i; + + /* show data for debug */ + MSG("\n"); + MSG("SYMBOL(dom_xen): %lx\n", SYMBOL(dom_xen)); + MSG("SYMBOL(dom_io): %lx\n", SYMBOL(dom_io)); + MSG("SYMBOL(domain_list): %lx\n", SYMBOL(domain_list)); + MSG("SYMBOL(xen_heap_start): %lx\n", SYMBOL(xen_heap_start)); + MSG("SYMBOL(frame_table): %lx\n", SYMBOL(frame_table)); + MSG("SYMBOL(alloc_bitmap): %lx\n", SYMBOL(alloc_bitmap)); + MSG("SYMBOL(max_page): %lx\n", SYMBOL(max_page)); + MSG("SYMBOL(pgd_l2): %lx\n", SYMBOL(pgd_l2)); + MSG("SYMBOL(pgd_l3): %lx\n", SYMBOL(pgd_l3)); + MSG("SYMBOL(pgd_l4): %lx\n", SYMBOL(pgd_l4)); + MSG("SYMBOL(xenheap_phys_end): %lx\n", SYMBOL(xenheap_phys_end)); + MSG("SYMBOL(xen_pstart): %lx\n", SYMBOL(xen_pstart)); + MSG("SYMBOL(frametable_pg_dir): %lx\n", SYMBOL(frametable_pg_dir)); + + MSG("SIZE(page_info): %ld\n", SIZE(page_info)); + MSG("OFFSET(page_info.count_info): %ld\n", OFFSET(page_info.count_info)); + MSG("OFFSET(page_info._domain): %ld\n", OFFSET(page_info._domain)); + MSG("SIZE(domain): %ld\n", SIZE(domain)); + MSG("OFFSET(domain.domain_id): %ld\n", OFFSET(domain.domain_id)); + MSG("OFFSET(domain.next_in_list): %ld\n", OFFSET(domain.next_in_list)); + + MSG("\n"); + MSG("frame_table_vaddr: %lx\n", info->frame_table_vaddr); + MSG("xen_heap_start: %lx\n", info->xen_heap_start); + MSG("xen_heap_end:%lx\n", info->xen_heap_end); + MSG("alloc_bitmap: %lx\n", info->alloc_bitmap); + MSG("max_page: %lx\n", info->max_page); + MSG("num_domain: %d\n", info->num_domain); + for (i = 0; i < info->num_domain; i++) { + MSG(" %u: %x: %lx\n", info->domain_list[i].domain_id, + info->domain_list[i].pickled_id, + info->domain_list[i].domain_addr); + } +} + +int +allocated_in_map(struct DumpInfo *info, unsigned long pfn) +{ + static int cur_idx = -1; + static unsigned long cur_word; + int idx; + + idx = pfn / PAGES_PER_MAPWORD; + if (idx != cur_idx) { + if (!readmem_xen(info, info->alloc_bitmap + idx * sizeof(unsigned long), + &cur_word, sizeof(cur_word), "Can''t access alloc_bitmap.\n")) + return 0; + cur_idx = idx; + } + + return !!(cur_word & (1UL << (pfn & (PAGES_PER_MAPWORD - 1)))); +} + +int +is_select_domain(struct DumpInfo *info, unsigned int id) +{ + int i; + + /* selected domain is fix to dom0 only now !! + (yes... domain_list is not necessary right now, + it can get from "dom0" directly) */ + + for (i = 0; i < info->num_domain; i++) { + if (info->domain_list[i].domain_id == 0 && + info->domain_list[i].pickled_id == id) + return TRUE; + } + + return FALSE; +} + +int +create_dump_bitmap_xen(struct DumpInfo *info) +{ + unsigned int remain_size; + struct cache_data bm2; + unsigned long page_info_addr; + unsigned long pfn; + unsigned int count_info; + unsigned int _domain; + int i; + struct pt_load_segment *pls; + int ret = FALSE; + + /* note: the first half of bitmap is not used for Xen extraction */ + bm2.fd = info->fd_bitmap; + bm2.file_name = info->name_bitmap; + bm2.cache_size = BUFSIZE_BITMAP; + bm2.buf_size = 0; + bm2.offset = info->len_bitmap/2; + bm2.buf = NULL; + + if ((bm2.buf = calloc(1, BUFSIZE_BITMAP)) == NULL) { + ERRMSG("Can''t allocate memory for 2nd-bitmap buffer. %s\n", + strerror(errno)); + goto out; + } + + pfn = 0; + for (i = 0; i < info->num_load_memory; i++) { + pls = &info->pt_load_segments[i]; + + for (; pfn < (unsigned long)(pls->phys_start >> PAGESHIFT()); pfn++) { /* memory hole */ + if ((pfn != 0) && (pfn%PFN_BUFBITMAP) == 0) { + bm2.buf_size = BUFSIZE_BITMAP; + if (!write_cache_bufsz(&bm2)) + goto out; + memset(bm2.buf, 0, BUFSIZE_BITMAP); + } + } + + for (; pfn < (unsigned long)(pls->phys_end >> PAGESHIFT()); pfn++) { + + if ((pfn != 0) && (pfn%PFN_BUFBITMAP) == 0) { + bm2.buf_size = BUFSIZE_BITMAP; + if (!write_cache_bufsz(&bm2)) + goto out; + memset(bm2.buf, 0, BUFSIZE_BITMAP); + } + + if (!allocated_in_map(info, pfn)) + continue; + + page_info_addr = info->frame_table_vaddr + pfn * SIZE(page_info); + if (!readmem_xen(info, + page_info_addr + OFFSET(page_info.count_info), + &count_info, sizeof(count_info), NULL)) { + continue; /* page_info may not exist */ + } + if (!readmem_xen(info, + page_info_addr + OFFSET(page_info._domain), + &_domain, sizeof(_domain), + "Can''t get page_info._domain.\n")) + goto out; + +// fprintf(stderr, "pfn: %lx\t%lx\t%lx\n", pfn, count_info, _domain); + /* + * select: + * - anonymous (_domain == 0), or + * - xen heap area, or + * - selected domain page + */ + if (_domain == 0 || + (info->xen_heap_start <= pfn && pfn < info->xen_heap_end) || + ((count_info & 0xffff) && is_select_domain(info, _domain))) { + set_bitmap(bm2.buf, pfn%PFN_BUFBITMAP, 1); + } + } + } + + /* + * Write the remainder of the bitmap. + */ + remain_size = info->len_bitmap - bm2.offset; + bm2.buf_size = remain_size; + if (!write_cache_bufsz(&bm2)) + goto out; + + ret = TRUE; +out: + if (bm2.buf != NULL) + free(bm2.buf); + + return ret; +} + +int +initial_xen(struct DumpInfo *info) +{ + if (!get_elf_info(info)) + return FALSE; + + if (!get_symbol_info_xen(info)) + return FALSE; + + if (!get_structure_info_xen(info)) + return FALSE; + + if (!get_xen_info(info)) + return FALSE; + + if (info->flag_debug) + show_data_xen(info); + + return TRUE; +} + +int +handle_xen(struct DumpInfo *info) +{ + if (!open_files_for_creating_dumpfile(info)) + goto out; + + if (!initial_xen(info)) + goto out; + + if (!create_dump_bitmap_xen(info)) + goto out; + + if (!write_elf_header(info)) + goto out; + if (!write_elf_pages(info)) + goto out; + + if (!close_files_for_creating_dumpfile(info)) + goto out; + + MSG("\n"); + MSG("The dumpfile is saved to %s.\n", info->name_dumpfile); + + return COMPLETED; +out: + return FALSE; +} + int main(int argc, char *argv[]) { @@ -4152,7 +4571,7 @@ vt = &info->vm_table; info->block_order = DEFAULT_ORDER; - while ((opt = getopt(argc, argv, "b:cDd:EFg:hi:Rvx:")) != -1) { + while ((opt = getopt(argc, argv, "b:cDd:EFg:hi:RvXx:")) != -1) { switch (opt) { case ''b'': info->block_order = atoi(optarg); @@ -4191,6 +4610,9 @@ case ''v'': info->flag_show_version = 1; break; + case ''X'': + info->flag_xen = 1; + break; case ''x'': info->flag_vmlinux = 1; dwarf_info.vmlinux_name = optarg; @@ -4282,6 +4704,18 @@ */ ERRMSG("Elf library out of date!\n"); goto out; + } + if (info->flag_xen) { + if (!info->flag_elf_dumpfile) { + ERRMSG("-E must be specified with -X.\n"); + goto out; + } + if (!info->flag_vmlinux) { + ERRMSG("-x xen-syms must be specified with -X.\n"); + goto out; + } + info->dump_level = DL_EXCLUDE_XEN; + return handle_xen(info); } if (info->flag_generate_config) { if (!open_files_for_generating_configfile(info)) Index: makedumpfile.h ==================================================================RCS file: /cvsroot/xen_ia64/people/oda/makedumpfile-1.1.3/makedumpfile.h,v retrieving revision 1.1 retrieving revision 1.13 diff -u -r1.1 -r1.13 --- makedumpfile.h 26 Apr 2007 02:32:30 -0000 1.1 +++ makedumpfile.h 27 May 2007 23:50:58 -0000 1.13 @@ -485,6 +485,7 @@ format to a standard out */ int flag_rearrange; /* flag of creating dumpfile from flattened format */ + int flag_xen; long page_size; /* size of page */ unsigned long long max_mapnr; /* number of page descriptor */ unsigned long section_size_bits; @@ -545,6 +546,18 @@ FILE *file_configfile; char *name_configfile; /* config file */ char release[65]; /*Can I define 65 automatically?*/ + + /* + * for Xen extraction + */ + unsigned long xen_heap_start; /* start mfn of xen heap area */ + unsigned long xen_heap_end; /* end mfn(+1) of xen heap area */ + unsigned long frame_table_vaddr; + unsigned long max_page; + unsigned long alloc_bitmap; + unsigned long dom0; + int num_domain; + struct domain_list *domain_list; }; struct symbol_table { @@ -560,6 +573,21 @@ unsigned long node_data; unsigned long pgdat_list; unsigned long contig_page_data; + + /* for Xen extraction */ + unsigned long dom_xen; + unsigned long dom_io; + unsigned long domain_list; + unsigned long frame_table; + unsigned long xen_heap_start; + unsigned long pgd_l2; + unsigned long pgd_l3; + unsigned long pgd_l4; + unsigned long xenheap_phys_end; + unsigned long xen_pstart; + unsigned long frametable_pg_dir; + unsigned long max_page; + unsigned long alloc_bitmap; }; struct size_table { @@ -569,6 +597,10 @@ long zone; long free_area; long list_head; + + /* for Xen extraction */ + long page_info; + long domain; }; struct offset_table { @@ -601,6 +633,16 @@ long next; long prev; } list_head; + + /* for Xen extraction */ + struct page_info { + long count_info; + long _domain; + } page_info; + struct domain { + long domain_id; + long next_in_list; + } domain; }; /* @@ -651,3 +693,89 @@ extern struct dwarf_info dwarf_info; +/* + * for Xen extraction + */ +struct domain_list { + unsigned long domain_addr; + unsigned int domain_id; + unsigned int pickled_id; +}; + +#define DL_EXCLUDE_XEN DL_EXCLUDE_FREE +#define PAGES_PER_MAPWORD (sizeof(unsigned long) * 8) + +extern int +readpmem(struct DumpInfo *info, unsigned long long paddr, void *bufptr, size_t size); +extern int +readmem_xen(struct DumpInfo *info, unsigned long long vaddr, void *bufptr, + size_t size, char *errmsg); + +#ifdef __x86__ +#define HYPERVISOR_VIRT_START_PAE (0xF5800000UL) +#define HYPERVISOR_VIRT_START (0xFC000000UL) +#define HYPERVISOR_VIRT_END (0xFFFFFFFFUL) +#define DIRECTMAP_VIRT_START (0xFF000000UL) +#define DIRECTMAP_VIRT_END (0xFFC00000UL) + +#define is_xen_vaddr(x) \ + ((x) >= HYPERVISOR_VIRT_START_PAE && (x) < HYPERVISOR_VIRT_END) +#define is_direct(x) \ + ((x) >= DIRECTMAP_VIRT_START && (x) < DIRECTMAP_VIRT_END) + +#define PGDIR_SHIFT_3LEVEL (30) +#define PTRS_PER_PTE_3LEVEL (512) +#define PTRS_PER_PGD_3LEVEL (4) +#define PMD_SHIFT (21) /* only used by PAE translators */ +#define PTRS_PER_PMD (512) /* only used by PAE translators */ +#define PTE_SHIFT (12) /* only used by PAE translators */ +#define PTRS_PER_PTE (512) /* only used by PAE translators */ + +#define _PAGE_PRESENT 0x001 +#define _PAGE_PSE 0x080 + +#define ENTRY_MASK (~0x8000000000000fffULL) + +unsigned long long kvtop_xen_x86(struct DumpInfo *info, unsigned long kvaddr); +#define kvtop_xen(X, Y) kvtop_xen_x86(X, Y) + +int get_xen_info_x86(struct DumpInfo *info); +#define get_xen_info_arch(X) get_xen_info_x86(X) + +#endif /* __x86__ */ + +#ifdef __ia64__ +#define HYPERVISOR_VIRT_START (0xe800000000000000) +#define HYPERVISOR_VIRT_END (0xf800000000000000) +#define DEFAULT_SHAREDINFO_ADDR (0xf100000000000000) +#define PERCPU_PAGE_SIZE 65536 +#define PERCPU_ADDR (DEFAULT_SHAREDINFO_ADDR - PERCPU_PAGE_SIZE) +#define DIRECTMAP_VIRT_START (0xf000000000000000) +#define DIRECTMAP_VIRT_END PERCPU_ADDR +#define VIRT_FRAME_TABLE_ADDR (0xf300000000000000) +#define VIRT_FRAME_TABLE_END (0xf400000000000000) + +#define is_xen_vaddr(x) \ + ((x) >= HYPERVISOR_VIRT_START && (x) < HYPERVISOR_VIRT_END) +#define is_direct(x) \ + ((x) >= DIRECTMAP_VIRT_START && (x) < DIRECTMAP_VIRT_END) +#define is_frame_table_vaddr(x) \ + ((x) >= VIRT_FRAME_TABLE_ADDR && (x) < VIRT_FRAME_TABLE_END) + +#define PGDIR_SHIFT (PAGESHIFT() + 2 * (PAGESHIFT() - 3)) +#define PTRS_PER_PGD (1UL << (PAGESHIFT() - 3)) +#define PMD_SHIFT (PAGESHIFT() + (PAGESHIFT() - 3)) +#define PTRS_PER_PMD (1UL << (PAGESHIFT() - 3)) +#define PTRS_PER_PTE (1UL << (PAGESHIFT() - 3)) + +#define IA64_MAX_PHYS_BITS 50 +#define _PAGE_P (1) +#define _PFN_MASK (((1UL << IA64_MAX_PHYS_BITS) - 1) & ~0xfffUL) + +unsigned long long kvtop_xen_ia64(struct DumpInfo *info, unsigned long kvaddr); +#define kvtop_xen(X, Y) kvtop_xen_ia64(X, Y) + +int get_xen_info_ia64(struct DumpInfo *info); +#define get_xen_info_arch(X) get_xen_info_ia64(X) + +#endif /* __ia64 */ Index: x86.c ==================================================================RCS file: /cvsroot/xen_ia64/people/oda/makedumpfile-1.1.3/x86.c,v retrieving revision 1.1 retrieving revision 1.6 diff -u -r1.1 -r1.6 --- x86.c 26 Apr 2007 02:32:30 -0000 1.1 +++ x86.c 26 May 2007 01:19:01 -0000 1.6 @@ -43,5 +43,98 @@ return TRUE; } +/* + * for Xen extraction + */ +unsigned long long +kvtop_xen_x86(struct DumpInfo *info, unsigned long kvaddr) +{ + unsigned long long dirp, entry; + + if (!is_xen_vaddr(kvaddr)) + return 0; + + if (is_direct(kvaddr)) + return (unsigned long)kvaddr - DIRECTMAP_VIRT_START; + + dirp = kvtop_xen_x86(info, SYMBOL(pgd_l3)); + dirp += ((kvaddr >> PGDIR_SHIFT_3LEVEL) & (PTRS_PER_PGD_3LEVEL - 1)) * sizeof(unsigned long long); + if (!readpmem(info, dirp, &entry, sizeof(entry))) + return 0; + + if (!(entry & _PAGE_PRESENT)) + return 0; + dirp = entry & ENTRY_MASK; + dirp += ((kvaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) * sizeof(unsigned long long); + if (!readpmem(info, dirp, &entry, sizeof(entry))) + return 0; + + if (!(entry & _PAGE_PRESENT)) + return 0; + if (entry & _PAGE_PSE) { + entry = (entry & ENTRY_MASK) + (kvaddr & ((1UL << PMD_SHIFT) - 1)); + return entry; + } + dirp = entry & ENTRY_MASK; + dirp += ((kvaddr >> PTE_SHIFT) & (PTRS_PER_PTE - 1)) * sizeof(unsigned long long); + if (!readpmem(info, dirp, &entry, sizeof(entry))) + return 0; + + if (!(entry & _PAGE_PRESENT)) { + return 0; + } + + entry = (entry & ENTRY_MASK) + (kvaddr & ((1UL << PTE_SHIFT) - 1)); + + return entry; +} + +int get_xen_info_x86(struct DumpInfo *info) +{ + unsigned long frame_table_vaddr; + unsigned long xen_end; + int i; + + if (SYMBOL(pgd_l2) == NOT_FOUND_SYMBOL && + SYMBOL(pgd_l3) == NOT_FOUND_SYMBOL) { + ERRMSG("Can''t get pgd.\n"); + return FALSE; + } + + if (SYMBOL(pgd_l3) == NOT_FOUND_SYMBOL) { + ERRMSG("non-PAE not support right now.\n"); + return FALSE; + } + + if (SYMBOL(frame_table) == NOT_FOUND_SYMBOL) { + ERRMSG("Can''t get the symbol of frame_table.\n"); + return FALSE; + } + if (!readmem_xen(info, SYMBOL(frame_table), &frame_table_vaddr, + sizeof(frame_table_vaddr), + "Can''t get the value of frame_table.\n")) + return FALSE; + + info->frame_table_vaddr = frame_table_vaddr; + + if (SYMBOL(xenheap_phys_end) == NOT_FOUND_SYMBOL) { + ERRMSG("Can''t get the symbol of xenheap_phys_end.\n"); + return FALSE; + } + if (!readmem_xen(info, SYMBOL(xenheap_phys_end), &xen_end, + sizeof(xen_end), "Can''t get the value of xenheap_phys_end.\n")) + return FALSE; + + info->xen_heap_end = (xen_end >> PAGESHIFT()); + info->xen_heap_start = 0; + + /* pickled_id == domain addr for x86 */ + for (i = 0; i < info->num_domain; i++) { + info->domain_list[i].pickled_id + info->domain_list[i].domain_addr; + } + + return TRUE; +} #endif /* x86 */ -- Itsuro ODA <oda@valinux.co.jp> _______________________________________________ kexec mailing list kexec@lists.infradead.org http://lists.infradead.org/mailman/listinfo/kexec --------------------- Original Message Ends -------------------- -- Itsuro ODA <oda@valinux.co.jp> _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel