diff options
| author | Kai Kang <kai.kang@windriver.com> | 2014-12-18 16:51:10 +0800 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2014-12-23 10:18:18 +0000 |
| commit | 8bf791c790ab552f207f3de324c683ed155cc3bf (patch) | |
| tree | ce5ade185ea1b4e8ef1bfde3660120e3b659ef2f | |
| parent | f78f9d7adb25d1c422b6e6f3371f1092c16157e3 (diff) | |
| download | poky-8bf791c790ab552f207f3de324c683ed155cc3bf.tar.gz | |
kexec-tools: add aarch64 support
Add patch from
https://fedorapeople.org/~hrw/aarch64/for-fedora/kexec-aarch64.patch
to add aarch64 support for kexec-tools.
(From OE-Core rev: 342ef3196bd754866bbdb54d538804ab71926553)
Signed-off-by: Kai Kang <kai.kang@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
| -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" |
