From: Keir Fraser Date: Fri, 13 Jun 2008 08:54:03 +0000 (+0100) Subject: extract vmcoreinfo from /proc/vmcore for Xen X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14192^2~78 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=65ce603cc1ca8882b22e3bf689b1958eedd40c97;p=xen.git extract vmcoreinfo from /proc/vmcore for Xen - the machine address and the size of the vmcoreinfo area is returned via the kexec_op(get_range) hypercall - fill the vmcoreinfo data when the kexec_op(crash load) hypercall is called Signed-off-by: Itsuro Oda --- diff --git a/xen/arch/ia64/xen/machine_kexec.c b/xen/arch/ia64/xen/machine_kexec.c index 221f59cf16..9fcd189d66 100644 --- a/xen/arch/ia64/xen/machine_kexec.c +++ b/xen/arch/ia64/xen/machine_kexec.c @@ -193,6 +193,15 @@ int machine_kexec_get(xen_kexec_range_t *range) return -EINVAL; } +void arch_crash_save_vmcoreinfo(void) +{ + VMCOREINFO_SYMBOL(dom_xen); + VMCOREINFO_SYMBOL(dom_io); + VMCOREINFO_SYMBOL(xen_pstart); + VMCOREINFO_SYMBOL(frametable_pg_dir); + VMCOREINFO_SYMBOL_ALIAS(xen_heap_start, xen_pickle_offset); +} + /* * Local variables: * mode: C diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index ceb4aa3cce..0a4994ba8b 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -189,7 +189,7 @@ static void domain_page_flush_and_put(struct domain* d, unsigned long mpaddr, extern unsigned long ia64_iobase; -static struct domain *dom_xen, *dom_io; +struct domain *dom_xen, *dom_io; /* * This number is bigger than DOMID_SELF, DOMID_XEN and DOMID_IO. diff --git a/xen/arch/x86/machine_kexec.c b/xen/arch/x86/machine_kexec.c index 4c2ccd8080..d98eb77fa7 100644 --- a/xen/arch/x86/machine_kexec.c +++ b/xen/arch/x86/machine_kexec.c @@ -145,6 +145,19 @@ int machine_kexec_get(xen_kexec_range_t *range) return machine_kexec_get_xen(range); } +void arch_crash_save_vmcoreinfo(void) +{ + VMCOREINFO_SYMBOL(dom_xen); + VMCOREINFO_SYMBOL(dom_io); + +#ifdef CONFIG_X86_PAE + VMCOREINFO_SYMBOL_ALIAS(pgd_l3, idle_pg_table); +#endif +#ifdef CONFIG_X86_64 + VMCOREINFO_SYMBOL_ALIAS(pgd_l4, idle_pg_table); +#endif +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 85530dad8d..af1033d1d7 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -151,7 +151,7 @@ static DEFINE_PER_CPU(struct percpu_mm_info, percpu_mm_info); #define FOREIGNDOM (this_cpu(percpu_mm_info).foreign ?: current->domain) /* Private domain structs for DOMID_XEN and DOMID_IO. */ -static struct domain *dom_xen, *dom_io; +struct domain *dom_xen, *dom_io; /* Frame table and its size in pages. */ struct page_info *frame_table; diff --git a/xen/common/kexec.c b/xen/common/kexec.c index 02f633d660..2eb73e94b5 100644 --- a/xen/common/kexec.c +++ b/xen/common/kexec.c @@ -43,6 +43,9 @@ static unsigned long kexec_flags = 0; /* the lowest bits are for KEXEC_IMAGE... static spinlock_t kexec_lock = SPIN_LOCK_UNLOCKED; +static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES]; +static size_t vmcoreinfo_size = 0; + xen_kexec_reserve_t kexec_crash_area; static void __init parse_crashkernel(const char *str) @@ -208,6 +211,13 @@ static int kexec_get_cpu(xen_kexec_range_t *range) return 0; } +static int kexec_get_vmcoreinfo(xen_kexec_range_t *range) +{ + range->start = __pa((unsigned long)vmcoreinfo_data); + range->size = VMCOREINFO_BYTES; + return 0; +} + static int kexec_get_range_internal(xen_kexec_range_t *range) { int ret = -EINVAL; @@ -220,6 +230,9 @@ static int kexec_get_range_internal(xen_kexec_range_t *range) case KEXEC_RANGE_MA_CPU: ret = kexec_get_cpu(range); break; + case KEXEC_RANGE_MA_VMCOREINFO: + ret = kexec_get_vmcoreinfo(range); + break; default: ret = machine_kexec_get(range); break; @@ -288,6 +301,56 @@ static int kexec_load_get_bits(int type, int *base, int *bit) return 0; } +void vmcoreinfo_append_str(const char *fmt, ...) +{ + va_list args; + char buf[0x50]; + int r; + size_t note_size = sizeof(Elf_Note) + ELFNOTE_ALIGN(strlen(VMCOREINFO_NOTE_NAME) + 1); + + if (vmcoreinfo_size + note_size + sizeof(buf) > VMCOREINFO_BYTES) + return; + + va_start(args, fmt); + r = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + + memcpy(&vmcoreinfo_data[note_size + vmcoreinfo_size], buf, r); + + vmcoreinfo_size += r; +} + +static void crash_save_vmcoreinfo(void) +{ + size_t data_size; + + if (vmcoreinfo_size > 0) /* already saved */ + return; + + data_size = VMCOREINFO_BYTES - (sizeof(Elf_Note) + ELFNOTE_ALIGN(strlen(VMCOREINFO_NOTE_NAME) + 1)); + setup_note((Elf_Note *)vmcoreinfo_data, VMCOREINFO_NOTE_NAME, 0, data_size); + + VMCOREINFO_PAGESIZE(PAGE_SIZE); + + VMCOREINFO_SYMBOL(domain_list); + VMCOREINFO_SYMBOL(frame_table); + VMCOREINFO_SYMBOL(alloc_bitmap); + VMCOREINFO_SYMBOL(max_page); + VMCOREINFO_SYMBOL(xenheap_phys_end); + + VMCOREINFO_STRUCT_SIZE(page_info); + VMCOREINFO_STRUCT_SIZE(domain); + + VMCOREINFO_OFFSET(page_info, count_info); + VMCOREINFO_OFFSET_ALIAS(page_info, u, _domain); + VMCOREINFO_OFFSET(domain, domain_id); + VMCOREINFO_OFFSET(domain, next_in_list); + +#ifdef ARCH_CRASH_SAVE_VMCOREINFO + arch_crash_save_vmcoreinfo(); +#endif +} + static int kexec_load_unload_internal(unsigned long op, xen_kexec_load_t *load) { xen_kexec_image_t *image; @@ -316,6 +379,8 @@ static int kexec_load_unload_internal(unsigned long op, xen_kexec_load_t *load) /* Make new image the active one */ change_bit(bit, &kexec_flags); } + + crash_save_vmcoreinfo(); } /* Unload the old image if present and load successful */ diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index d1773c679e..410622cdd2 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -102,7 +102,7 @@ static unsigned long scrub_pages; * One bit per page of memory. Bit set => page is allocated. */ -static unsigned long *alloc_bitmap; +unsigned long *alloc_bitmap; #define PAGES_PER_MAPWORD (sizeof(unsigned long) * 8) #define allocated_in_map(_pn) \ diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index dc557bfca3..24d2495b34 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -295,4 +295,6 @@ struct screen_info { }; #define CONFIG_XENCOMM_MARK_DIRTY 1 +#define ARCH_CRASH_SAVE_VMCOREINFO + #endif /* _IA64_CONFIG_H_ */ diff --git a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h index 716e9bd7c5..a5871cc712 100644 --- a/xen/include/asm-ia64/mm.h +++ b/xen/include/asm-ia64/mm.h @@ -503,4 +503,6 @@ int steal_page( unsigned long domain_get_maximum_gpfn(struct domain *d); +extern struct domain *dom_xen, *dom_io; /* for vmcoreinfo */ + #endif /* __ASM_IA64_MM_H__ */ diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index c2d8ad1d6a..19bb4209f5 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -371,4 +371,6 @@ extern unsigned long xen_phys_start, xenheap_phys_start, xenheap_phys_end; #define ELFSIZE 32 #endif +#define ARCH_CRASH_SAVE_VMCOREINFO + #endif /* __X86_CONFIG_H__ */ diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 73c24fb2c3..bd8af02ff2 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -357,4 +357,6 @@ unsigned int domain_clamp_alloc_bitsize(struct domain *d, unsigned int bits); unsigned long domain_get_maximum_gpfn(struct domain *d); +extern struct domain *dom_xen, *dom_io; /* for vmcoreinfo */ + #endif /* __ASM_X86_MM_H__ */ diff --git a/xen/include/public/kexec.h b/xen/include/public/kexec.h index fbad3606ac..ac1743c93d 100644 --- a/xen/include/public/kexec.h +++ b/xen/include/public/kexec.h @@ -138,6 +138,7 @@ typedef struct xen_kexec_load { * the ia64_boot_param */ #define KEXEC_RANGE_MA_EFI_MEMMAP 5 /* machine address and size of * of the EFI Memory Map */ +#define KEXEC_RANGE_MA_VMCOREINFO 6 /* machine address and size of vmcoreinfo */ /* * Find the address and size of certain memory areas @@ -154,6 +155,27 @@ typedef struct xen_kexec_range { unsigned long start; } xen_kexec_range_t; +/* vmcoreinfo stuff */ +#define VMCOREINFO_BYTES (4096) +#define VMCOREINFO_NOTE_NAME "VMCOREINFO_XEN" +void arch_crash_save_vmcoreinfo(void); +void vmcoreinfo_append_str(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); +#define VMCOREINFO_PAGESIZE(value) \ + vmcoreinfo_append_str("PAGESIZE=%ld\n", value) +#define VMCOREINFO_SYMBOL(name) \ + vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name) +#define VMCOREINFO_SYMBOL_ALIAS(alias, name) \ + vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #alias, (unsigned long)&name) +#define VMCOREINFO_STRUCT_SIZE(name) \ + vmcoreinfo_append_str("SIZE(%s)=%zu\n", #name, sizeof(struct name)) +#define VMCOREINFO_OFFSET(name, field) \ + vmcoreinfo_append_str("OFFSET(%s.%s)=%zu\n", #name, #field, \ + offsetof(struct name, field)) +#define VMCOREINFO_OFFSET_ALIAS(name, field, alias) \ + vmcoreinfo_append_str("OFFSET(%s.%s)=%zu\n", #name, #alias, \ + offsetof(struct name, field)) + #endif /* _XEN_PUBLIC_KEXEC_H */ /* diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h index 1341bb0fa0..08bd72d8ce 100644 --- a/xen/include/xen/mm.h +++ b/xen/include/xen/mm.h @@ -104,4 +104,6 @@ int guest_remove_page(struct domain *d, unsigned long gmfn); /* Returns TRUE if the memory at address @p is ordinary RAM. */ int memory_is_conventional_ram(paddr_t p); +extern unsigned long *alloc_bitmap; /* for vmcoreinfo */ + #endif /* __XEN_MM_H__ */