diff options
-rw-r--r-- | meta/recipes-kernel/kexec/kexec-tools.inc | 2 | ||||
-rw-r--r-- | meta/recipes-kernel/kexec/kexec-tools/kexec-aarch64.patch | 801 | ||||
-rw-r--r-- | meta/recipes-kernel/kexec/kexec-tools_2.0.8.bb | 4 |
3 files changed, 805 insertions, 2 deletions
diff --git a/meta/recipes-kernel/kexec/kexec-tools.inc b/meta/recipes-kernel/kexec/kexec-tools.inc index 7e3b7adfc7..312424a88f 100644 --- a/meta/recipes-kernel/kexec/kexec-tools.inc +++ b/meta/recipes-kernel/kexec/kexec-tools.inc | |||
@@ -12,7 +12,7 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/utils/kernel/kexec/kexec-tools-${PV}.tar.gz | |||
12 | 12 | ||
13 | inherit autotools-brokensep | 13 | inherit autotools-brokensep |
14 | 14 | ||
15 | COMPATIBLE_HOST = '(x86_64.*|i.86.*|arm.*|powerpc.*|mips.*)-(linux|freebsd.*)' | 15 | COMPATIBLE_HOST = '(x86_64.*|i.86.*|arm.*|aarch64.*|powerpc.*|mips.*)-(linux|freebsd.*)' |
16 | 16 | ||
17 | INSANE_SKIP_${PN} = "arch" | 17 | INSANE_SKIP_${PN} = "arch" |
18 | 18 | ||
diff --git a/meta/recipes-kernel/kexec/kexec-tools/kexec-aarch64.patch b/meta/recipes-kernel/kexec/kexec-tools/kexec-aarch64.patch new file mode 100644 index 0000000000..b697a54b90 --- /dev/null +++ b/meta/recipes-kernel/kexec/kexec-tools/kexec-aarch64.patch | |||
@@ -0,0 +1,801 @@ | |||
1 | From: Geoff Levand <geoff@infradead.org> | ||
2 | Date: Mon, 15 Jul 2013 23:32:36 +0000 (-0700) | ||
3 | Subject: Add arm64 support | ||
4 | X-Git-Url: https://git.linaro.org/gitweb?p=people%2Fgeoff%2Fkexec-tools.git;a=commitdiff_plain;h=fbf5ac6c2c70ec0f6da2b9ff563e573999752c01 | ||
5 | |||
6 | Add arm64 support | ||
7 | |||
8 | Signed-off-by: Geoff Levand <geoff@infradead.org> | ||
9 | |||
10 | Get patch from: | ||
11 | https://fedorapeople.org/~hrw/aarch64/for-fedora/kexec-aarch64.patch | ||
12 | |||
13 | Upstream-Status: Pending | ||
14 | |||
15 | Signed-off-by: Kai Kang <kai.kang@windriver.com> | ||
16 | --- | ||
17 | |||
18 | Index: kexec-tools-2.0.4/configure.ac | ||
19 | =================================================================== | ||
20 | --- kexec-tools-2.0.4.orig/configure.ac | ||
21 | +++ kexec-tools-2.0.4/configure.ac | ||
22 | @@ -30,6 +30,9 @@ case $target_cpu in | ||
23 | powerpc64 ) | ||
24 | ARCH="ppc64" | ||
25 | ;; | ||
26 | + aarch64 ) | ||
27 | + ARCH="arm64" | ||
28 | + ;; | ||
29 | arm* ) | ||
30 | ARCH="arm" | ||
31 | ;; | ||
32 | Index: kexec-tools-2.0.4/kexec/Makefile | ||
33 | =================================================================== | ||
34 | --- kexec-tools-2.0.4.orig/kexec/Makefile | ||
35 | +++ kexec-tools-2.0.4/kexec/Makefile | ||
36 | @@ -70,6 +70,7 @@ KEXEC_SRCS += $($(ARCH)_FS2DT) | ||
37 | |||
38 | include $(srcdir)/kexec/arch/alpha/Makefile | ||
39 | include $(srcdir)/kexec/arch/arm/Makefile | ||
40 | +include $(srcdir)/kexec/arch/arm64/Makefile | ||
41 | include $(srcdir)/kexec/arch/i386/Makefile | ||
42 | include $(srcdir)/kexec/arch/ia64/Makefile | ||
43 | include $(srcdir)/kexec/arch/mips/Makefile | ||
44 | Index: kexec-tools-2.0.4/kexec/arch/arm64/Makefile | ||
45 | =================================================================== | ||
46 | --- /dev/null | ||
47 | +++ kexec-tools-2.0.4/kexec/arch/arm64/Makefile | ||
48 | @@ -0,0 +1,13 @@ | ||
49 | + | ||
50 | +arm64_KEXEC_SRCS += \ | ||
51 | + kexec/arch/arm64/kexec-arm64.c \ | ||
52 | + kexec/arch/arm64/kexec-elf-arm64.c \ | ||
53 | + kexec/arch/arm64/crashdump-arm64.c | ||
54 | + | ||
55 | +arm64_ARCH_REUSE_INITRD = | ||
56 | +arm64_ADD_SEGMENT = | ||
57 | +arm64_VIRT_TO_PHYS = | ||
58 | + | ||
59 | +dist += $(arm64_KEXEC_SRCS) \ | ||
60 | + kexec/arch/arm64/Makefile \ | ||
61 | + kexec/arch/arm64/kexec-arm64.h | ||
62 | Index: kexec-tools-2.0.4/kexec/arch/arm64/crashdump-arm64.c | ||
63 | =================================================================== | ||
64 | --- /dev/null | ||
65 | +++ kexec-tools-2.0.4/kexec/arch/arm64/crashdump-arm64.c | ||
66 | @@ -0,0 +1,305 @@ | ||
67 | +/* | ||
68 | + * This program is free software; you can redistribute it and/or modify | ||
69 | + * it under the terms of the GNU General Public License as published by | ||
70 | + * the Free Software Foundation (version 2 of the License). | ||
71 | + */ | ||
72 | + | ||
73 | +#include "../../kexec.h" | ||
74 | +#include "../../kexec-elf.h" | ||
75 | +#include "../../crashdump.h" | ||
76 | + | ||
77 | +int is_crashkernel_mem_reserved(void) | ||
78 | +{ | ||
79 | + return 0; | ||
80 | +} | ||
81 | + | ||
82 | +#if 0 | ||
83 | +/* | ||
84 | + * Used to save various memory ranges/regions needed for the captured | ||
85 | + * kernel to boot. (lime memmap= option in other archs) | ||
86 | + */ | ||
87 | +static struct memory_range crash_memory_ranges[CRASH_MAX_MEMORY_RANGES]; | ||
88 | +struct memory_ranges usablemem_rgns = { | ||
89 | + .size = 0, | ||
90 | + .ranges = crash_memory_ranges, | ||
91 | +}; | ||
92 | + | ||
93 | +/* memory range reserved for crashkernel */ | ||
94 | +static struct memory_range crash_reserved_mem; | ||
95 | + | ||
96 | +static struct crash_elf_info elf_info = { | ||
97 | + .class = ELFCLASS32, | ||
98 | + .data = ELFDATA2LSB, | ||
99 | + .machine = EM_ARM, | ||
100 | + .page_offset = PAGE_OFFSET, | ||
101 | +}; | ||
102 | + | ||
103 | +unsigned long phys_offset; | ||
104 | + | ||
105 | +/** | ||
106 | + * crash_range_callback() - callback called for each iomem region | ||
107 | + * @data: not used | ||
108 | + * @nr: not used | ||
109 | + * @str: name of the memory region | ||
110 | + * @base: start address of the memory region | ||
111 | + * @length: size of the memory region | ||
112 | + * | ||
113 | + * This function is called once for each memory region found in /proc/iomem. It | ||
114 | + * locates system RAM and crashkernel reserved memory and places these to | ||
115 | + * variables: @crash_memory_ranges and @crash_reserved_mem. Number of memory | ||
116 | + * regions is placed in @crash_memory_nr_ranges. | ||
117 | + */ | ||
118 | +static int crash_range_callback(void *UNUSED(data), int UNUSED(nr), | ||
119 | + char *str, unsigned long base, | ||
120 | + unsigned long length) | ||
121 | +{ | ||
122 | + struct memory_range *range; | ||
123 | + | ||
124 | + if (usablemem_rgns.size >= CRASH_MAX_MEMORY_RANGES) | ||
125 | + return 1; | ||
126 | + | ||
127 | + range = usablemem_rgns.ranges + usablemem_rgns.size; | ||
128 | + | ||
129 | + if (strncmp(str, "System RAM\n", 11) == 0) { | ||
130 | + range->start = base; | ||
131 | + range->end = base + length - 1; | ||
132 | + range->type = RANGE_RAM; | ||
133 | + usablemem_rgns.size++; | ||
134 | + } else if (strncmp(str, "Crash kernel\n", 13) == 0) { | ||
135 | + crash_reserved_mem.start = base; | ||
136 | + crash_reserved_mem.end = base + length - 1; | ||
137 | + crash_reserved_mem.type = RANGE_RAM; | ||
138 | + } | ||
139 | + | ||
140 | + return 0; | ||
141 | +} | ||
142 | + | ||
143 | +/** | ||
144 | + * crash_exclude_range() - excludes memory region reserved for crashkernel | ||
145 | + * | ||
146 | + * Function locates where crashkernel reserved memory is and removes that region | ||
147 | + * from the available memory regions. | ||
148 | + */ | ||
149 | +static void crash_exclude_range(void) | ||
150 | +{ | ||
151 | + const struct memory_range *range = &crash_reserved_mem; | ||
152 | + int i; | ||
153 | + | ||
154 | + for (i = 0; i < usablemem_rgns.size; i++) { | ||
155 | + struct memory_range *r = usablemem_rgns.ranges + i; | ||
156 | + | ||
157 | + /* | ||
158 | + * We assume that crash area is fully contained in | ||
159 | + * some larger memory area. | ||
160 | + */ | ||
161 | + if (r->start <= range->start && r->end >= range->end) { | ||
162 | + struct memory_range *new; | ||
163 | + /* | ||
164 | + * Let's split this area into 2 smaller ones and | ||
165 | + * remove excluded range from between. First create | ||
166 | + * new entry for the remaining area. | ||
167 | + */ | ||
168 | + new = usablemem_rgns.ranges + usablemem_rgns.size; | ||
169 | + new->start = range->end + 1; | ||
170 | + new->end = r->end; | ||
171 | + usablemem_rgns.size++; | ||
172 | + /* | ||
173 | + * Next update this area to end before excluded range. | ||
174 | + */ | ||
175 | + r->end = range->start - 1; | ||
176 | + break; | ||
177 | + } | ||
178 | + } | ||
179 | +} | ||
180 | + | ||
181 | +static int range_cmp(const void *a1, const void *a2) | ||
182 | +{ | ||
183 | + const struct memory_range *r1 = a1; | ||
184 | + const struct memory_range *r2 = a2; | ||
185 | + | ||
186 | + if (r1->start > r2->start) | ||
187 | + return 1; | ||
188 | + if (r1->start < r2->start) | ||
189 | + return -1; | ||
190 | + | ||
191 | + return 0; | ||
192 | +} | ||
193 | + | ||
194 | +/** | ||
195 | + * crash_get_memory_ranges() - read system physical memory | ||
196 | + * | ||
197 | + * Function reads through system physical memory and stores found memory regions | ||
198 | + * in @crash_memory_ranges. Number of memory regions found is placed in | ||
199 | + * @crash_memory_nr_ranges. Regions are sorted in ascending order. | ||
200 | + * | ||
201 | + * Returns %0 in case of success and %-1 otherwise (errno is set). | ||
202 | + */ | ||
203 | +static int crash_get_memory_ranges(void) | ||
204 | +{ | ||
205 | + /* | ||
206 | + * First read all memory regions that can be considered as | ||
207 | + * system memory including the crash area. | ||
208 | + */ | ||
209 | + kexec_iomem_for_each_line(NULL, crash_range_callback, NULL); | ||
210 | + | ||
211 | + if (usablemem_rgns.size < 1) { | ||
212 | + errno = EINVAL; | ||
213 | + return -1; | ||
214 | + } | ||
215 | + | ||
216 | + /* | ||
217 | + * Exclude memory reserved for crashkernel (this may result a split memory | ||
218 | + * region). | ||
219 | + */ | ||
220 | + crash_exclude_range(); | ||
221 | + | ||
222 | + /* | ||
223 | + * Make sure that the memory regions are sorted. | ||
224 | + */ | ||
225 | + qsort(usablemem_rgns.ranges, usablemem_rgns.size, | ||
226 | + sizeof(*usablemem_rgns.ranges), range_cmp); | ||
227 | + | ||
228 | + return 0; | ||
229 | +} | ||
230 | + | ||
231 | +/** | ||
232 | + * cmdline_add_elfcorehdr() - adds elfcorehdr= to @cmdline | ||
233 | + * @cmdline: buffer where parameter is placed | ||
234 | + * @elfcorehdr: physical address of elfcorehdr | ||
235 | + * | ||
236 | + * Function appends 'elfcorehdr=start' at the end of the command line given in | ||
237 | + * @cmdline. Note that @cmdline must be at least %COMMAND_LINE_SIZE bytes long | ||
238 | + * (inclunding %NUL). | ||
239 | + */ | ||
240 | +static void cmdline_add_elfcorehdr(char *cmdline, unsigned long elfcorehdr) | ||
241 | +{ | ||
242 | + char buf[COMMAND_LINE_SIZE]; | ||
243 | + int buflen; | ||
244 | + | ||
245 | + buflen = snprintf(buf, sizeof(buf), "%s elfcorehdr=%#lx", | ||
246 | + cmdline, elfcorehdr); | ||
247 | + if (buflen < 0) | ||
248 | + die("Failed to construct elfcorehdr= command line parameter\n"); | ||
249 | + if (buflen >= sizeof(buf)) | ||
250 | + die("Command line overflow\n"); | ||
251 | + | ||
252 | + (void) strncpy(cmdline, buf, COMMAND_LINE_SIZE); | ||
253 | + cmdline[COMMAND_LINE_SIZE - 1] = '\0'; | ||
254 | +} | ||
255 | + | ||
256 | +/** | ||
257 | + * cmdline_add_mem() - adds mem= parameter to kernel command line | ||
258 | + * @cmdline: buffer where parameter is placed | ||
259 | + * @size: size of the kernel reserved memory (in bytes) | ||
260 | + * | ||
261 | + * This function appends 'mem=size' at the end of the command line given in | ||
262 | + * @cmdline. Note that @cmdline must be at least %COMMAND_LINE_SIZE bytes long | ||
263 | + * (including %NUL). | ||
264 | + */ | ||
265 | +static void cmdline_add_mem(char *cmdline, unsigned long size) | ||
266 | +{ | ||
267 | + char buf[COMMAND_LINE_SIZE]; | ||
268 | + int buflen; | ||
269 | + | ||
270 | + buflen = snprintf(buf, sizeof(buf), "%s mem=%ldK", cmdline, size >> 10); | ||
271 | + if (buflen < 0) | ||
272 | + die("Failed to construct mem= command line parameter\n"); | ||
273 | + if (buflen >= sizeof(buf)) | ||
274 | + die("Command line overflow\n"); | ||
275 | + | ||
276 | + (void) strncpy(cmdline, buf, COMMAND_LINE_SIZE); | ||
277 | + cmdline[COMMAND_LINE_SIZE - 1] = '\0'; | ||
278 | +} | ||
279 | + | ||
280 | +static unsigned long long range_size(const struct memory_range *r) | ||
281 | +{ | ||
282 | + return r->end - r->start + 1; | ||
283 | +} | ||
284 | + | ||
285 | +static void dump_memory_ranges(void) | ||
286 | +{ | ||
287 | + int i; | ||
288 | + | ||
289 | + if (!kexec_debug) | ||
290 | + return; | ||
291 | + | ||
292 | + dbgprintf("crashkernel: [%#llx - %#llx] (%ldM)\n", | ||
293 | + crash_reserved_mem.start, crash_reserved_mem.end, | ||
294 | + (unsigned long)range_size(&crash_reserved_mem) >> 20); | ||
295 | + | ||
296 | + for (i = 0; i < usablemem_rgns.size; i++) { | ||
297 | + struct memory_range *r = usablemem_rgns.ranges + i; | ||
298 | + dbgprintf("memory range: [%#llx - %#llx] (%ldM)\n", | ||
299 | + r->start, r->end, (unsigned long)range_size(r) >> 20); | ||
300 | + } | ||
301 | +} | ||
302 | + | ||
303 | +/** | ||
304 | + * load_crashdump_segments() - loads additional segments needed for kdump | ||
305 | + * @info: kexec info structure | ||
306 | + * @mod_cmdline: kernel command line | ||
307 | + * | ||
308 | + * This function loads additional segments which are needed for the dump capture | ||
309 | + * kernel. It also updates kernel command line passed in @mod_cmdline to have | ||
310 | + * right parameters for the dump capture kernel. | ||
311 | + * | ||
312 | + * Return %0 in case of success and %-1 in case of error. | ||
313 | + */ | ||
314 | +int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline) | ||
315 | +{ | ||
316 | + unsigned long elfcorehdr; | ||
317 | + unsigned long bufsz; | ||
318 | + void *buf; | ||
319 | + int err; | ||
320 | + | ||
321 | + /* | ||
322 | + * First fetch all the memory (RAM) ranges that we are going to pass to | ||
323 | + * the crashdump kernel during panic. | ||
324 | + */ | ||
325 | + err = crash_get_memory_ranges(); | ||
326 | + if (err) | ||
327 | + return err; | ||
328 | + | ||
329 | + /* | ||
330 | + * Now that we have memory regions sorted, we can use first memory | ||
331 | + * region as PHYS_OFFSET. | ||
332 | + */ | ||
333 | + phys_offset = usablemem_rgns.ranges->start; | ||
334 | + dbgprintf("phys_offset: %#lx\n", phys_offset); | ||
335 | + | ||
336 | + err = crash_create_elf32_headers(info, &elf_info, | ||
337 | + usablemem_rgns.ranges, | ||
338 | + usablemem_rgns.size, &buf, &bufsz, | ||
339 | + ELF_CORE_HEADER_ALIGN); | ||
340 | + if (err) | ||
341 | + return err; | ||
342 | + | ||
343 | + /* | ||
344 | + * We allocate ELF core header from the end of the memory area reserved | ||
345 | + * for the crashkernel. We align the header to SECTION_SIZE (which is | ||
346 | + * 1MB) so that available memory passed in kernel command line will be | ||
347 | + * aligned to 1MB. This is because kernel create_mapping() wants memory | ||
348 | + * regions to be aligned to SECTION_SIZE. | ||
349 | + */ | ||
350 | + elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 1 << 20, | ||
351 | + crash_reserved_mem.start, | ||
352 | + crash_reserved_mem.end, -1, 0); | ||
353 | + | ||
354 | + dbgprintf("elfcorehdr: %#lx\n", elfcorehdr); | ||
355 | + cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr); | ||
356 | + | ||
357 | + /* | ||
358 | + * Add 'mem=size' parameter to dump capture kernel command line. This | ||
359 | + * prevents the dump capture kernel from using any other memory regions | ||
360 | + * which belong to the primary kernel. | ||
361 | + */ | ||
362 | + cmdline_add_mem(mod_cmdline, elfcorehdr - crash_reserved_mem.start); | ||
363 | + | ||
364 | + dump_memory_ranges(); | ||
365 | + dbgprintf("kernel command line: \"%s\"\n", mod_cmdline); | ||
366 | + | ||
367 | + return 0; | ||
368 | +} | ||
369 | + | ||
370 | +#endif | ||
371 | + | ||
372 | Index: kexec-tools-2.0.4/kexec/arch/arm64/include/arch/options.h | ||
373 | =================================================================== | ||
374 | --- /dev/null | ||
375 | +++ kexec-tools-2.0.4/kexec/arch/arm64/include/arch/options.h | ||
376 | @@ -0,0 +1,26 @@ | ||
377 | +#ifndef KEXEC_ARCH_ARM64_OPTIONS_H | ||
378 | +#define KEXEC_ARCH_ARM64_OPTIONS_H | ||
379 | + | ||
380 | +//#define OPT_ARCH_MAX ((OPT_MAX)+0) | ||
381 | + | ||
382 | +#define OPT_APPEND ((OPT_MAX)+0) | ||
383 | +#define OPT_RAMDISK ((OPT_MAX)+1) | ||
384 | +#define OPT_DTB ((OPT_MAX)+2) | ||
385 | + | ||
386 | +#define OPT_ARCH_MAX ((OPT_MAX)+3) | ||
387 | + | ||
388 | + | ||
389 | +#define KEXEC_ARCH_OPTIONS \ | ||
390 | + KEXEC_OPTIONS \ | ||
391 | + { "append", 1, NULL, OPT_APPEND }, \ | ||
392 | + { "command-line", 1, NULL, OPT_APPEND }, \ | ||
393 | + { "dtb", 1, NULL, OPT_DTB }, \ | ||
394 | + { "initrd", 1, NULL, OPT_RAMDISK }, \ | ||
395 | + { "ramdisk", 1, NULL, OPT_RAMDISK }, \ | ||
396 | + | ||
397 | +#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */ | ||
398 | + | ||
399 | +#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS | ||
400 | +#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR | ||
401 | + | ||
402 | +#endif /* KEXEC_ARCH_ARM64_OPTIONS_H */ | ||
403 | Index: kexec-tools-2.0.4/kexec/arch/arm64/kexec-arm64.c | ||
404 | =================================================================== | ||
405 | --- /dev/null | ||
406 | +++ kexec-tools-2.0.4/kexec/arch/arm64/kexec-arm64.c | ||
407 | @@ -0,0 +1,177 @@ | ||
408 | +/* | ||
409 | + * ARM64 kexec support. | ||
410 | + */ | ||
411 | + | ||
412 | +#define _GNU_SOURCE | ||
413 | + | ||
414 | +#include <errno.h> | ||
415 | +#include <stddef.h> | ||
416 | + | ||
417 | +//#include <linux/kexec.h> | ||
418 | + | ||
419 | +#include "../../kexec.h" | ||
420 | +#include "../../kexec-syscall.h" | ||
421 | +#include "kexec-arm64.h" | ||
422 | + | ||
423 | + | ||
424 | +void arch_usage(void) | ||
425 | +{ | ||
426 | + fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__); | ||
427 | + | ||
428 | + printf( | ||
429 | +" --append=STRING Set the kernel command line to STRING.\n" | ||
430 | +" --command-line=STRING Set the kernel command line to STRING.\n" | ||
431 | +" --dtb=FILE Use FILE as the device tree blob.\n" | ||
432 | +" --initrd=FILE Use FILE as the kernel initial ramdisk.\n" | ||
433 | +" --ramdisk=FILE Use FILE as the kernel initial ramdisk.\n"); | ||
434 | + | ||
435 | + fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__); | ||
436 | +} | ||
437 | + | ||
438 | +int arch_process_options(int UNUSED(argc), char **UNUSED(argv)) | ||
439 | +{ | ||
440 | + fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); | ||
441 | + return 0; | ||
442 | +} | ||
443 | + | ||
444 | +const struct arch_map_entry arches[] = { | ||
445 | + { "aarch64", KEXEC_ARCH_ARM64 }, | ||
446 | + { NULL, 0 }, | ||
447 | +}; | ||
448 | + | ||
449 | +void arch_update_purgatory(struct kexec_info *UNUSED(info)) | ||
450 | +{ | ||
451 | + fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); | ||
452 | +} | ||
453 | + | ||
454 | +unsigned long virt_to_phys(unsigned long addr) | ||
455 | +{ | ||
456 | + fprintf(stderr, "%s:%d: %016lx -> %016lx\n", __func__, __LINE__, addr, | ||
457 | + addr + 0x080000000UL); | ||
458 | + return addr + 0x080000000UL; | ||
459 | +} | ||
460 | + | ||
461 | +void add_segment(struct kexec_info *info, const void *buf, size_t bufsz, | ||
462 | + unsigned long base, size_t memsz) | ||
463 | +{ | ||
464 | + fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__); | ||
465 | + add_segment_phys_virt(info, buf, bufsz, base, memsz, 1); | ||
466 | + fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__); | ||
467 | +} | ||
468 | + | ||
469 | +static int get_memory_ranges_1(struct memory_range **range, int *ranges, | ||
470 | + unsigned long kexec_flags) | ||
471 | +{ | ||
472 | + static struct memory_range memory_range[KEXEC_SEGMENT_MAX]; | ||
473 | + const char *iomem; | ||
474 | + int range_count = 0; | ||
475 | + char line[MAX_LINE]; | ||
476 | + FILE *fp; | ||
477 | + | ||
478 | + iomem = proc_iomem(); | ||
479 | + fp = fopen(iomem, "r"); | ||
480 | + | ||
481 | + if (!fp) { | ||
482 | + fprintf(stderr, "Cannot open %s: %s\n", | ||
483 | + iomem, strerror(errno)); | ||
484 | + return -1; | ||
485 | + } | ||
486 | + | ||
487 | + dbgprintf("memory ranges:\n"); | ||
488 | + | ||
489 | + while(fgets(line, sizeof(line), fp) != 0) { | ||
490 | + struct memory_range r; | ||
491 | + char *str; | ||
492 | + int consumed; | ||
493 | + | ||
494 | + if (range_count >= KEXEC_SEGMENT_MAX) | ||
495 | + break; | ||
496 | + | ||
497 | + if (sscanf(line, "%Lx-%Lx : %n", &r.start, &r.end, &consumed) | ||
498 | + != 2) | ||
499 | + continue; | ||
500 | + | ||
501 | + str = line + consumed; | ||
502 | + r.end++; | ||
503 | + | ||
504 | + if (memcmp(str, "System RAM\n", 11)) { | ||
505 | + dbgprintf(" Skip: %016Lx - %016Lx : %s", r.start, r.end, | ||
506 | + str); | ||
507 | + continue; | ||
508 | + } | ||
509 | + | ||
510 | + r.type = RANGE_RAM; | ||
511 | + memory_range[range_count] = r; | ||
512 | + range_count++; | ||
513 | + | ||
514 | + dbgprintf(" Add: %016Lx - %016Lx : %s", r.start, r.end, str); | ||
515 | + } | ||
516 | + | ||
517 | + fclose(fp); | ||
518 | + *range = memory_range; | ||
519 | + *ranges = range_count; | ||
520 | + | ||
521 | + return 0; | ||
522 | +} | ||
523 | + | ||
524 | +static int get_memory_ranges_2(struct memory_range **range, int *ranges, | ||
525 | + unsigned long UNUSED(kexec_flags)) | ||
526 | +{ | ||
527 | + static struct memory_range memory_range[2]; | ||
528 | + | ||
529 | + memory_range[0].start = 0x080000000; | ||
530 | + memory_range[0].end = 0x100000000; | ||
531 | + memory_range[0].type = RANGE_RAM; | ||
532 | + | ||
533 | + memory_range[1].start = 0x900000000; | ||
534 | + memory_range[1].end = 0x880000000; | ||
535 | + memory_range[1].type = RANGE_RAM; | ||
536 | + | ||
537 | + *range = memory_range; | ||
538 | + *ranges = sizeof(memory_range) / sizeof(memory_range[0]); | ||
539 | + | ||
540 | + return 0; | ||
541 | +} | ||
542 | + | ||
543 | +int get_memory_ranges(struct memory_range **range, int *ranges, | ||
544 | + unsigned long kexec_flags) | ||
545 | +{ | ||
546 | + /* FIXME: Should get this info from device tree. */ | ||
547 | + | ||
548 | + return get_memory_ranges_1(range, ranges, kexec_flags); | ||
549 | +} | ||
550 | + | ||
551 | +struct file_type file_type[] = { | ||
552 | + { "elf-arm64", elf_arm64_probe, elf_arm64_load, elf_arm64_usage }, | ||
553 | +}; | ||
554 | + | ||
555 | +int file_types = sizeof(file_type) / sizeof(file_type[0]); | ||
556 | + | ||
557 | +int arch_compat_trampoline(struct kexec_info *info) | ||
558 | +{ | ||
559 | + fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); | ||
560 | + return 0; | ||
561 | +} | ||
562 | + | ||
563 | +void arch_reuse_initrd(void) | ||
564 | +{ | ||
565 | +} | ||
566 | + | ||
567 | +int machine_verify_elf_rel(struct mem_ehdr *ehdr) | ||
568 | +{ | ||
569 | + (void)ehdr; | ||
570 | + | ||
571 | + fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); | ||
572 | + return 0; | ||
573 | +} | ||
574 | + | ||
575 | +void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, | ||
576 | + void *location, unsigned long address, unsigned long value) | ||
577 | +{ | ||
578 | + (void)ehdr; | ||
579 | + (void)r_type; | ||
580 | + (void)location; | ||
581 | + (void)address; | ||
582 | + (void)value; | ||
583 | + fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); | ||
584 | +} | ||
585 | Index: kexec-tools-2.0.4/kexec/arch/arm64/kexec-arm64.h | ||
586 | =================================================================== | ||
587 | --- /dev/null | ||
588 | +++ kexec-tools-2.0.4/kexec/arch/arm64/kexec-arm64.h | ||
589 | @@ -0,0 +1,20 @@ | ||
590 | +/* | ||
591 | + * ARM64 kexec support. | ||
592 | + */ | ||
593 | + | ||
594 | +#if !defined(KEXEC_ARM64_H) | ||
595 | +#define KEXEC_ARM64_H | ||
596 | + | ||
597 | +/* #include <linux/kexec.h> FIXME: this is broken */ | ||
598 | +#include <sys/types.h> | ||
599 | + | ||
600 | +#include "../../kexec.h" | ||
601 | + | ||
602 | +#define KEXEC_SEGMENT_MAX 16 /* FIXME: this should come from <linux/kexec.h> */ | ||
603 | + | ||
604 | +int elf_arm64_probe(const char *buf, off_t len); | ||
605 | +int elf_arm64_load(int argc, char **argv, const char *buf, off_t len, | ||
606 | + struct kexec_info *info); | ||
607 | +void elf_arm64_usage(void); | ||
608 | + | ||
609 | +#endif | ||
610 | \ No newline at end of file | ||
611 | Index: kexec-tools-2.0.4/kexec/arch/arm64/kexec-elf-arm64.c | ||
612 | =================================================================== | ||
613 | --- /dev/null | ||
614 | +++ kexec-tools-2.0.4/kexec/arch/arm64/kexec-elf-arm64.c | ||
615 | @@ -0,0 +1,114 @@ | ||
616 | +/* | ||
617 | + * ARM64 kexec support. | ||
618 | + */ | ||
619 | + | ||
620 | +#define _GNU_SOURCE | ||
621 | + | ||
622 | +#include <elf.h> | ||
623 | +#include <getopt.h> | ||
624 | + | ||
625 | +#include "../../kexec-syscall.h" | ||
626 | + | ||
627 | +#include "kexec-arm64.h" | ||
628 | +#include "arch/options.h" | ||
629 | + | ||
630 | +#if !defined(EM_AARCH64) | ||
631 | +# define EM_AARCH64 183 | ||
632 | +#endif | ||
633 | + | ||
634 | +int elf_arm64_probe(const char *buf, off_t len) | ||
635 | +{ | ||
636 | + int result; | ||
637 | + struct mem_ehdr ehdr; | ||
638 | + | ||
639 | + fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__); | ||
640 | + | ||
641 | + result = build_elf_exec_info(buf, len, &ehdr, 0); | ||
642 | + | ||
643 | + if (result < 0) { | ||
644 | + dbgprintf("Not an ELF executable\n"); | ||
645 | + goto out; | ||
646 | + } | ||
647 | + | ||
648 | + if (ehdr.e_machine != EM_AARCH64) { | ||
649 | + dbgprintf("Not an AARCH64 executable\n"); | ||
650 | + result = -1; | ||
651 | + goto out; | ||
652 | + } | ||
653 | + | ||
654 | + result = 0; | ||
655 | + | ||
656 | +out: | ||
657 | + free_elf_info(&ehdr); | ||
658 | + fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__); | ||
659 | + return result; | ||
660 | +} | ||
661 | + | ||
662 | +int elf_arm64_load(int argc, char **argv, const char *buf, off_t len, | ||
663 | + struct kexec_info *info) | ||
664 | +{ | ||
665 | + static const struct option options[] = { | ||
666 | + KEXEC_ARCH_OPTIONS | ||
667 | + { 0 } | ||
668 | + }; | ||
669 | + static const char short_options[] = KEXEC_OPT_STR ""; | ||
670 | + const char *command_line = NULL; | ||
671 | + unsigned int command_line_len = 0; | ||
672 | + const char *ramdisk = NULL; | ||
673 | + const char *dtb = NULL; | ||
674 | + int opt; | ||
675 | + struct mem_ehdr ehdr; | ||
676 | + int result; | ||
677 | + | ||
678 | + fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__); | ||
679 | + | ||
680 | + while ((opt = getopt_long(argc, argv, short_options, options, 0)) | ||
681 | + != -1) { | ||
682 | + switch (opt) { | ||
683 | + default: | ||
684 | + if (opt < OPT_MAX) /* Ignore core options */ | ||
685 | + break; | ||
686 | + case OPT_APPEND: | ||
687 | + command_line = optarg; | ||
688 | + command_line_len = strlen(command_line) + 1; | ||
689 | + break; | ||
690 | + case OPT_RAMDISK: | ||
691 | + ramdisk = optarg; | ||
692 | + break; | ||
693 | + case OPT_DTB: | ||
694 | + dtb = optarg; | ||
695 | + break; | ||
696 | + } | ||
697 | + } | ||
698 | + | ||
699 | + fprintf(stderr, "%s:%d: command_line: %s\n", __func__, __LINE__, command_line); | ||
700 | + fprintf(stderr, "%s:%d: ramdisk: %s\n", __func__, __LINE__, ramdisk); | ||
701 | + fprintf(stderr, "%s:%d: dtb: %s\n", __func__, __LINE__, dtb); | ||
702 | + | ||
703 | + if (info->kexec_flags & KEXEC_ON_CRASH) { | ||
704 | + fprintf(stderr, "kexec: kdump not yet supported on arm64\n"); | ||
705 | + return -1; | ||
706 | + } | ||
707 | + | ||
708 | + result = build_elf_exec_info(buf, len, &ehdr, 0); | ||
709 | + | ||
710 | + if (result < 0) { | ||
711 | + free_elf_info(&ehdr); | ||
712 | + fprintf(stderr, "%s:%d: free_elf_info failed\n", __func__, | ||
713 | + __LINE__); | ||
714 | + return result; | ||
715 | + } | ||
716 | + | ||
717 | + elf_exec_build_load(info, &ehdr, buf, len, 0); | ||
718 | + | ||
719 | + info->entry = (void*)0x80080000UL; // FIXME | ||
720 | + | ||
721 | + fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__); | ||
722 | + return 0; | ||
723 | +} | ||
724 | + | ||
725 | +void elf_arm64_usage(void) | ||
726 | +{ | ||
727 | + fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__); | ||
728 | + fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__); | ||
729 | +} | ||
730 | Index: kexec-tools-2.0.4/kexec/kexec-syscall.h | ||
731 | =================================================================== | ||
732 | --- kexec-tools-2.0.4.orig/kexec/kexec-syscall.h | ||
733 | +++ kexec-tools-2.0.4/kexec/kexec-syscall.h | ||
734 | @@ -39,8 +39,8 @@ | ||
735 | #ifdef __s390__ | ||
736 | #define __NR_kexec_load 277 | ||
737 | #endif | ||
738 | -#ifdef __arm__ | ||
739 | -#define __NR_kexec_load __NR_SYSCALL_BASE + 347 | ||
740 | +#if defined(__arm__) || defined(__arm64__) | ||
741 | +#define __NR_kexec_load __NR_SYSCALL_BASE + 347 | ||
742 | #endif | ||
743 | #if defined(__mips__) | ||
744 | #define __NR_kexec_load 4311 | ||
745 | @@ -72,6 +72,8 @@ static inline long kexec_load(void *entr | ||
746 | #define KEXEC_ARCH_PPC64 (21 << 16) | ||
747 | #define KEXEC_ARCH_IA_64 (50 << 16) | ||
748 | #define KEXEC_ARCH_ARM (40 << 16) | ||
749 | +#define KEXEC_ARCH_ARM64 (183 << 16) | ||
750 | +/* #define KEXEC_ARCH_AARCH64 (183 << 16) */ | ||
751 | #define KEXEC_ARCH_S390 (22 << 16) | ||
752 | #define KEXEC_ARCH_SH (42 << 16) | ||
753 | #define KEXEC_ARCH_MIPS_LE (10 << 16) | ||
754 | @@ -114,5 +116,8 @@ static inline long kexec_load(void *entr | ||
755 | #if defined(__mips__) | ||
756 | #define KEXEC_ARCH_NATIVE KEXEC_ARCH_MIPS | ||
757 | #endif | ||
758 | +#if defined(__arm64__) | ||
759 | +#define KEXEC_ARCH_NATIVE KEXEC_ARCH_ARM64 | ||
760 | +#endif | ||
761 | |||
762 | #endif /* KEXEC_SYSCALL_H */ | ||
763 | Index: kexec-tools-2.0.4/kexec/kexec.c | ||
764 | =================================================================== | ||
765 | --- kexec-tools-2.0.4.orig/kexec/kexec.c | ||
766 | +++ kexec-tools-2.0.4/kexec/kexec.c | ||
767 | @@ -659,6 +659,8 @@ static int my_load(const char *type, int | ||
768 | info.backup_start = 0; | ||
769 | info.kexec_flags = kexec_flags; | ||
770 | |||
771 | + fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); | ||
772 | + | ||
773 | result = 0; | ||
774 | if (argc - fileind <= 0) { | ||
775 | fprintf(stderr, "No kernel specified\n"); | ||
776 | Index: kexec-tools-2.0.4/purgatory/arch/arm64/Makefile | ||
777 | =================================================================== | ||
778 | --- /dev/null | ||
779 | +++ kexec-tools-2.0.4/purgatory/arch/arm64/Makefile | ||
780 | @@ -0,0 +1,7 @@ | ||
781 | +# | ||
782 | +# Purgatory arm64 | ||
783 | +# | ||
784 | + | ||
785 | +arm64_PURGATORY_SRCS = | ||
786 | + | ||
787 | +dist += purgatory/arch/arm64/Makefile $(arm64_PURGATORY_SRCS) | ||
788 | Index: kexec-tools-2.0.4/configure | ||
789 | =================================================================== | ||
790 | --- kexec-tools-2.0.4.orig/configure | ||
791 | +++ kexec-tools-2.0.4/configure | ||
792 | @@ -2256,6 +2256,9 @@ case $target_cpu in | ||
793 | powerpc64 ) | ||
794 | ARCH="ppc64" | ||
795 | ;; | ||
796 | + aarch64 ) | ||
797 | + ARCH="arm64" | ||
798 | + ;; | ||
799 | arm* ) | ||
800 | ARCH="arm" | ||
801 | ;; | ||
diff --git a/meta/recipes-kernel/kexec/kexec-tools_2.0.8.bb b/meta/recipes-kernel/kexec/kexec-tools_2.0.8.bb index 559bc6a25d..c478732300 100644 --- a/meta/recipes-kernel/kexec/kexec-tools_2.0.8.bb +++ b/meta/recipes-kernel/kexec/kexec-tools_2.0.8.bb | |||
@@ -2,7 +2,9 @@ require kexec-tools.inc | |||
2 | export LDFLAGS = "-L${STAGING_LIBDIR}" | 2 | export LDFLAGS = "-L${STAGING_LIBDIR}" |
3 | EXTRA_OECONF = " --with-zlib=yes" | 3 | EXTRA_OECONF = " --with-zlib=yes" |
4 | 4 | ||
5 | SRC_URI += "file://kexec-tools-Refine-kdump-device_tree-sort.patch" | 5 | SRC_URI += "file://kexec-tools-Refine-kdump-device_tree-sort.patch \ |
6 | file://kexec-aarch64.patch \ | ||
7 | " | ||
6 | 8 | ||
7 | SRC_URI[md5sum] = "45bd2bc676ae202579e4c185563126af" | 9 | SRC_URI[md5sum] = "45bd2bc676ae202579e4c185563126af" |
8 | SRC_URI[sha256sum] = "95083c707577154a2241c5af0985f1eb3412d1ba208ef91813e9158b0a901179" | 10 | SRC_URI[sha256sum] = "95083c707577154a2241c5af0985f1eb3412d1ba208ef91813e9158b0a901179" |