1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#define _GNU_SOURCE
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <elf.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "kexec.h"
#include "crashdump.h"
#include "kexec-syscall.h"
#include "config.h"
#ifdef HAVE_LIBXENCTRL
#include <xenctrl.h>
#endif
struct crash_note_info {
unsigned long base;
unsigned long length;
};
static int xen_phys_cpus;
static struct crash_note_info *xen_phys_notes;
static int is_dom0;
int xen_present(void)
{
if (!is_dom0) {
if (access("/proc/xen/capabilities", F_OK) == 0)
is_dom0 = 1;
else
is_dom0 = -1;
}
return is_dom0 > 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;
}
|