#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "kexec.h" #include "crashdump.h" #include "kexec-syscall.h" #include "config.h" #ifdef HAVE_LIBXENCTRL #include #endif struct crash_note_info { unsigned long base; unsigned long length; }; int xen_phys_cpus = 0; struct crash_note_info *xen_phys_notes; int xen_present(void) { struct stat buf; return stat("/proc/xen", &buf) == 0; } unsigned long xen_architecture(struct crash_elf_info *elf_info) { unsigned long machine = elf_info->machine; #ifdef HAVE_LIBXENCTRL int xc, rc; xen_capabilities_info_t capabilities; if (!xen_present()) goto out; memset(capabilities, '0', XEN_CAPABILITIES_INFO_LEN); xc = xc_interface_open(); if ( xc == -1 ) { fprintf(stderr, "failed to open xen control interface.\n"); goto out; } rc = xc_version(xc, XENVER_capabilities, &capabilities[0]); if ( rc == -1 ) { fprintf(stderr, "failed to make Xen version hypercall.\n"); goto out_close; } if (strstr(capabilities, "xen-3.0-x86_64")) machine = EM_X86_64; else if (strstr(capabilities, "xen-3.0-x86_32")) machine = EM_386; out_close: xc_interface_close(xc); out: #endif return machine; } static int xen_crash_note_callback(void *UNUSED(data), int nr, char *UNUSED(str), unsigned long base, unsigned long length) { struct crash_note_info *note = xen_phys_notes + nr; note->base = base; note->length = length; return 0; } int xen_get_nr_phys_cpus(void) { char *match = "Crash note\n"; int cpus, n; if (xen_phys_cpus) return xen_phys_cpus; if ((cpus = kexec_iomem_for_each_line(match, NULL, NULL))) { n = sizeof(struct crash_note_info) * cpus; xen_phys_notes = malloc(n); if (!xen_phys_notes) { fprintf(stderr, "failed to allocate xen_phys_notes.\n"); return -1; } memset(xen_phys_notes, 0, n); kexec_iomem_for_each_line(match, xen_crash_note_callback, NULL); xen_phys_cpus = cpus; } return cpus; } int xen_get_note(int cpu, uint64_t *addr, uint64_t *len) { struct crash_note_info *note; if (xen_phys_cpus <= 0) return -1; note = xen_phys_notes + cpu; *addr = note->base; *len = note->length; return 0; }