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