[cns3xxx]: workaround serial hang with SMP enabled
[openwrt/svn-archive/archive.git] / package / kexec-tools / patches / 0005-mips64_support.patch
1 --- a/kexec/arch/mips/Makefile
2 +++ b/kexec/arch/mips/Makefile
3 @@ -4,7 +4,7 @@
4 mips_KEXEC_SRCS = kexec/arch/mips/kexec-mips.c
5 mips_KEXEC_SRCS += kexec/arch/mips/kexec-elf-mips.c
6 mips_KEXEC_SRCS += kexec/arch/mips/kexec-elf-rel-mips.c
7 -mips_KEXEC_SRCS += kexec/arch/mips/mips-setup-simple.S
8 +mips_KEXEC_SRCS += kexec/arch/mips/crashdump-mips.c
9
10 mips_ADD_BUFFER =
11 mips_ADD_SEGMENT =
12 --- /dev/null
13 +++ b/kexec/arch/mips/crashdump-mips.c
14 @@ -0,0 +1,371 @@
15 +/*
16 + * kexec: Linux boots Linux
17 + *
18 + * 2005 (C) IBM Corporation.
19 + * 2008 (C) MontaVista Software, Inc.
20 + *
21 + * This program is free software; you can redistribute it and/or modify
22 + * it under the terms of the GNU General Public License as published by
23 + * the Free Software Foundation (version 2 of the License).
24 + *
25 + * This program is distributed in the hope that it will be useful,
26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 + * GNU General Public License for more details.
29 + *
30 + * You should have received a copy of the GNU General Public License
31 + * along with this program; if not, write to the Free Software
32 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 + */
34 +#include <stdio.h>
35 +#include <string.h>
36 +#include <stdlib.h>
37 +#include <errno.h>
38 +#include <elf.h>
39 +#include <sys/types.h>
40 +#include <sys/stat.h>
41 +#include <unistd.h>
42 +#include "../../kexec.h"
43 +#include "../../kexec-elf.h"
44 +#include "../../kexec-syscall.h"
45 +#include "../../crashdump.h"
46 +#include "kexec-mips.h"
47 +#include "crashdump-mips.h"
48 +
49 +extern struct arch_options_t arch_options;
50 +
51 +/* Stores a sorted list of RAM memory ranges for which to create elf headers.
52 + * A separate program header is created for backup region */
53 +static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES];
54 +
55 +/* Memory region reserved for storing panic kernel and other data. */
56 +static struct memory_range crash_reserved_mem;
57 +
58 +/*
59 + * To store the memory size of the first kernel and this value will be
60 + * passed to the second kernel as command line (savemaxmem=xM).
61 + * The second kernel will be calculated saved_max_pfn based on this
62 + * variable.
63 + */
64 +unsigned long long saved_max_mem = 0;
65 +
66 +/* Removes crash reserve region from list of memory chunks for whom elf program
67 + * headers have to be created. Assuming crash reserve region to be a single
68 + * continuous area fully contained inside one of the memory chunks */
69 +static int exclude_crash_reserve_region(int *nr_ranges)
70 +{
71 + int i, j, tidx = -1;
72 + unsigned long long cstart, cend;
73 + struct memory_range temp_region;
74 +
75 + /* Crash reserved region. */
76 + cstart = crash_reserved_mem.start;
77 + cend = crash_reserved_mem.end;
78 +
79 + for (i = 0; i < (*nr_ranges); i++) {
80 + unsigned long long mstart, mend;
81 + mstart = crash_memory_range[i].start;
82 + mend = crash_memory_range[i].end;
83 + if (cstart < mend && cend > mstart) {
84 + if (cstart != mstart && cend != mend) {
85 + /* Split memory region */
86 + crash_memory_range[i].end = cstart - 1;
87 + temp_region.start = cend + 1;
88 + temp_region.end = mend;
89 + temp_region.type = RANGE_RAM;
90 + tidx = i+1;
91 + } else if (cstart != mstart)
92 + crash_memory_range[i].end = cstart - 1;
93 + else
94 + crash_memory_range[i].start = cend + 1;
95 + }
96 + }
97 + /* Insert split memory region, if any. */
98 + if (tidx >= 0) {
99 + if (*nr_ranges == CRASH_MAX_MEMORY_RANGES) {
100 + /* No space to insert another element. */
101 + fprintf(stderr, "Error: Number of crash memory ranges"
102 + " excedeed the max limit\n");
103 + return -1;
104 + }
105 + for (j = (*nr_ranges - 1); j >= tidx; j--)
106 + crash_memory_range[j+1] = crash_memory_range[j];
107 + crash_memory_range[tidx].start = temp_region.start;
108 + crash_memory_range[tidx].end = temp_region.end;
109 + crash_memory_range[tidx].type = temp_region.type;
110 + (*nr_ranges)++;
111 + }
112 + return 0;
113 +}
114 +/* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to
115 + * create Elf headers. Keeping it separate from get_memory_ranges() as
116 + * requirements are different in the case of normal kexec and crashdumps.
117 + *
118 + * Normal kexec needs to look at all of available physical memory irrespective
119 + * of the fact how much of it is being used by currently running kernel.
120 + * Crashdumps need to have access to memory regions actually being used by
121 + * running kernel. Expecting a different file/data structure than /proc/iomem
122 + * to look into down the line. May be something like /proc/kernelmem or may
123 + * be zone data structures exported from kernel.
124 + */
125 +static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
126 +{
127 + const char iomem[]= "/proc/iomem";
128 + int i, memory_ranges = 0;
129 + char line[MAX_LINE];
130 + FILE *fp;
131 + unsigned long long start, end;
132 +
133 + fp = fopen(iomem, "r");
134 + if (!fp) {
135 + fprintf(stderr, "Cannot open %s: %s\n",
136 + iomem, strerror(errno));
137 + return -1;
138 + }
139 +
140 + /* Separate segment for backup region */
141 + crash_memory_range[0].start = BACKUP_SRC_START;
142 + crash_memory_range[0].end = BACKUP_SRC_END;
143 + crash_memory_range[0].type = RANGE_RAM;
144 + memory_ranges++;
145 +
146 + while(fgets(line, sizeof(line), fp) != 0) {
147 + char *str;
148 + int type, consumed, count;
149 + if (memory_ranges >= CRASH_MAX_MEMORY_RANGES)
150 + break;
151 + count = sscanf(line, "%Lx-%Lx : %n",
152 + &start, &end, &consumed);
153 + if (count != 2)
154 + continue;
155 + str = line + consumed;
156 +
157 + /* Only Dumping memory of type System RAM. */
158 + if (memcmp(str, "System RAM\n", 11) == 0) {
159 + type = RANGE_RAM;
160 + } else if (memcmp(str, "Crash kernel\n", 13) == 0) {
161 + /* Reserved memory region. New kernel can
162 + * use this region to boot into. */
163 + crash_reserved_mem.start = start;
164 + crash_reserved_mem.end = end;
165 + crash_reserved_mem.type = RANGE_RAM;
166 + continue;
167 + } else {
168 + continue;
169 + }
170 +
171 + if (start == BACKUP_SRC_START && end >= (BACKUP_SRC_END + 1))
172 + start = BACKUP_SRC_END + 1;
173 +
174 + crash_memory_range[memory_ranges].start = start;
175 + crash_memory_range[memory_ranges].end = end;
176 + crash_memory_range[memory_ranges].type = type;
177 + memory_ranges++;
178 +
179 + /* Segregate linearly mapped region. */
180 + if ((MAXMEM - 1) >= start && (MAXMEM - 1) <= end) {
181 + crash_memory_range[memory_ranges-1].end = MAXMEM -1;
182 +
183 + /* Add segregated region. */
184 + crash_memory_range[memory_ranges].start = MAXMEM;
185 + crash_memory_range[memory_ranges].end = end;
186 + crash_memory_range[memory_ranges].type = type;
187 + memory_ranges++;
188 + }
189 + }
190 + fclose(fp);
191 +
192 + if (exclude_crash_reserve_region(&memory_ranges) < 0)
193 + return -1;
194 +
195 + for (i = 0; i < memory_ranges; i++)
196 + if (saved_max_mem < crash_memory_range[i].end)
197 + saved_max_mem = crash_memory_range[i].end + 1;
198 +
199 + *range = crash_memory_range;
200 + *ranges = memory_ranges;
201 + return 0;
202 +}
203 +
204 +/* Converts unsigned long to ascii string. */
205 +static void ultoa(unsigned long i, char *str)
206 +{
207 + int j = 0, k;
208 + char tmp;
209 +
210 + do {
211 + str[j++] = i % 10 + '0';
212 + } while ((i /=10) > 0);
213 + str[j] = '\0';
214 +
215 + /* Reverse the string. */
216 + for (j = 0, k = strlen(str) - 1; j < k; j++, k--) {
217 + tmp = str[k];
218 + str[k] = str[j];
219 + str[j] = tmp;
220 + }
221 +}
222 +
223 +/* Adds the appropriate mem= options to command line, indicating the
224 + * memory region the new kernel can use to boot into. */
225 +static int cmdline_add_mem(char *cmdline, unsigned long addr, unsigned long size)
226 +{
227 + int cmdlen, len;
228 + char str[50], *ptr;
229 +
230 + addr = addr/1024;
231 + size = size/1024;
232 + ptr = str;
233 + strcpy (str, " mem=");
234 + ptr += strlen(str);
235 + ultoa(size, ptr);
236 + strcat (str, "K@");
237 + ptr = str + strlen(str);
238 + ultoa(addr, ptr);
239 + strcat (str, "K");
240 + len = strlen(str);
241 + cmdlen = strlen(cmdline) + len;
242 + if (cmdlen > (COMMAND_LINE_SIZE - 1))
243 + die("Command line overflow\n");
244 + strcat(cmdline, str);
245 +
246 + return 0;
247 +}
248 +
249 +/* Adds the elfcorehdr= command line parameter to command line. */
250 +static int cmdline_add_elfcorehdr(char *cmdline, unsigned long addr)
251 +{
252 + int cmdlen, len, align = 1024;
253 + char str[30], *ptr;
254 +
255 + /* Passing in elfcorehdr=xxxK format. Saves space required in cmdline.
256 + * Ensure 1K alignment*/
257 + if (addr%align)
258 + return -1;
259 + addr = addr/align;
260 + ptr = str;
261 + strcpy(str, " elfcorehdr=");
262 + ptr += strlen(str);
263 + ultoa(addr, ptr);
264 + strcat(str, "K");
265 + len = strlen(str);
266 + cmdlen = strlen(cmdline) + len;
267 + if (cmdlen > (COMMAND_LINE_SIZE - 1))
268 + die("Command line overflow\n");
269 + strcat(cmdline, str);
270 + return 0;
271 +}
272 +
273 +/* Adds the elfcorehdr= command line parameter to command line. */
274 +static int cmdline_add_savemaxmem(char *cmdline, unsigned long addr)
275 +{
276 + int cmdlen, len, align = 1024;
277 + char str[30], *ptr;
278 +
279 + /* Passing in savemaxmem=xxxM format. Saves space required in cmdline.*/
280 + addr = addr/(align*align);
281 + ptr = str;
282 + strcpy(str, " savemaxmem=");
283 + ptr += strlen(str);
284 + ultoa(addr, ptr);
285 + strcat(str, "M");
286 + len = strlen(str);
287 + cmdlen = strlen(cmdline) + len;
288 + if (cmdlen > (COMMAND_LINE_SIZE - 1))
289 + die("Command line overflow\n");
290 + strcat(cmdline, str);
291 + return 0;
292 +}
293 +
294 +#ifdef __mips64
295 +static struct crash_elf_info elf_info64 =
296 +{
297 + class: ELFCLASS64,
298 + data: ELFDATA2MSB,
299 + machine: EM_MIPS,
300 + backup_src_start: BACKUP_SRC_START,
301 + backup_src_end: BACKUP_SRC_END,
302 + page_offset: PAGE_OFFSET,
303 + lowmem_limit: MAXMEM,
304 +};
305 +#endif
306 +static struct crash_elf_info elf_info32 =
307 +{
308 + class: ELFCLASS32,
309 + data: ELFDATA2MSB,
310 + machine: EM_MIPS,
311 + backup_src_start: BACKUP_SRC_START,
312 + backup_src_end: BACKUP_SRC_END,
313 + page_offset: PAGE_OFFSET,
314 + lowmem_limit: MAXMEM,
315 +};
316 +
317 +/* Loads additional segments in case of a panic kernel is being loaded.
318 + * One segment for backup region, another segment for storing elf headers
319 + * for crash memory image.
320 + */
321 +int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
322 + unsigned long max_addr, unsigned long min_base)
323 +{
324 + void *tmp;
325 + unsigned long sz, elfcorehdr;
326 + int nr_ranges, align = 1024;
327 + struct memory_range *mem_range;
328 +
329 + if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0)
330 + return -1;
331 +
332 + /* Create a backup region segment to store backup data*/
333 + sz = (BACKUP_SRC_SIZE + align - 1) & ~(align - 1);
334 + tmp = xmalloc(sz);
335 + memset(tmp, 0, sz);
336 + info->backup_start = add_buffer(info, tmp, sz, sz, align,
337 + crash_reserved_mem.start,
338 + crash_reserved_mem.end,-1);
339 +
340 +#ifdef __mips64
341 + /* Create elf header segment and store crash image data. */
342 + if (arch_options.core_header_type == CORE_TYPE_ELF64) {
343 + if (crash_create_elf64_headers(info, &elf_info64,
344 + crash_memory_range, nr_ranges,
345 + &tmp, &sz,
346 + ELF_CORE_HEADER_ALIGN) < 0)
347 + return -1;
348 + }
349 + else {
350 + if (crash_create_elf32_headers(info, &elf_info32,
351 + crash_memory_range, nr_ranges,
352 + &tmp, &sz,
353 + ELF_CORE_HEADER_ALIGN) < 0)
354 + return -1;
355 + }
356 +#else
357 + if (crash_create_elf32_headers(info, &elf_info32,
358 + crash_memory_range, nr_ranges,
359 + &tmp, &sz,
360 + ELF_CORE_HEADER_ALIGN) < 0)
361 + return -1;
362 +#endif
363 + elfcorehdr = add_buffer(info, tmp, sz, sz, align,
364 + crash_reserved_mem.start,
365 + crash_reserved_mem.end, -1);
366 +
367 + /*
368 + * backup segment is after elfcorehdr, so use elfcorehdr as top of
369 + * kernel's available memory
370 + */
371 + cmdline_add_mem(mod_cmdline, crash_reserved_mem.start,
372 + elfcorehdr - crash_reserved_mem.start);
373 + cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
374 + cmdline_add_savemaxmem(mod_cmdline, saved_max_mem);
375 + return 0;
376 +}
377 +
378 +int is_crashkernel_mem_reserved(void)
379 +{
380 + uint64_t start, end;
381 +
382 + return parse_iomem_single("Crash kernel\n", &start, &end) == 0 ?
383 + (start != end) : 0;
384 +}
385 +
386 --- /dev/null
387 +++ b/kexec/arch/mips/crashdump-mips.h
388 @@ -0,0 +1,26 @@
389 +#ifndef CRASHDUMP_MIPS_H
390 +#define CRASHDUMP_MIPS_H
391 +
392 +struct kexec_info;
393 +int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline,
394 + unsigned long max_addr, unsigned long min_base);
395 +#ifdef __mips64
396 +#define PAGE_OFFSET 0xa800000000000000ULL
397 +#else
398 +#define PAGE_OFFSET 0x80000000
399 +#endif
400 +#define __pa(x) ((unsigned long)(X)& 0x7fffffff)
401 +
402 +#define MAXMEM 0x80000000
403 +
404 +#define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1)
405 +#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2)
406 +
407 +#define COMMAND_LINE_SIZE 512
408 +
409 +/* Backup Region, First 1M of System RAM. */
410 +#define BACKUP_SRC_START 0x00000000
411 +#define BACKUP_SRC_END 0x000fffff
412 +#define BACKUP_SRC_SIZE (BACKUP_SRC_END - BACKUP_SRC_START + 1)
413 +
414 +#endif /* CRASHDUMP_MIPS_H */
415 --- a/kexec/arch/mips/include/arch/options.h
416 +++ b/kexec/arch/mips/include/arch/options.h
417 @@ -2,10 +2,21 @@
418 #define KEXEC_ARCH_MIPS_OPTIONS_H
419
420 #define OPT_ARCH_MAX (OPT_MAX+0)
421 +#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
422
423 +#ifdef __mips64
424 +#define OPT_ELF64_CORE (OPT_MAX+1)
425 #define KEXEC_ARCH_OPTIONS \
426 KEXEC_OPTIONS \
427 + { "elf64-core-headers", 0, 0, OPT_ELF64_CORE }, \
428
429 #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR ""
430 +#define OPT_ARCH_MAX (OPT_MAX+2)
431 +#else
432 +#define KEXEC_ARCH_OPTIONS \
433 + KEXEC_OPTIONS \
434 +
435 +#define OPT_ARCH_MAX (OPT_MAX+0)
436 +#endif
437
438 #endif /* KEXEC_ARCH_MIPS_OPTIONS_H */
439 --- a/kexec/arch/mips/kexec-elf-mips.c
440 +++ b/kexec/arch/mips/kexec-elf-mips.c
441 @@ -25,51 +25,18 @@
442 #include <ip_checksum.h>
443 #include "../../kexec.h"
444 #include "../../kexec-elf.h"
445 +#include "../../kexec-syscall.h"
446 #include "kexec-mips.h"
447 #include <arch/options.h>
448 +#include "crashdump-mips.h"
449
450 static const int probe_debug = 0;
451
452 #define BOOTLOADER "kexec"
453 #define MAX_COMMAND_LINE 256
454
455 -#define UPSZ(X) ((sizeof(X) + 3) & ~3)
456 -static struct boot_notes {
457 - Elf_Bhdr hdr;
458 - Elf_Nhdr bl_hdr;
459 - unsigned char bl_desc[UPSZ(BOOTLOADER)];
460 - Elf_Nhdr blv_hdr;
461 - unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
462 - Elf_Nhdr cmd_hdr;
463 - unsigned char command_line[0];
464 -} elf_boot_notes = {
465 - .hdr = {
466 - .b_signature = 0x0E1FB007,
467 - .b_size = sizeof(elf_boot_notes),
468 - .b_checksum = 0,
469 - .b_records = 3,
470 - },
471 - .bl_hdr = {
472 - .n_namesz = 0,
473 - .n_descsz = sizeof(BOOTLOADER),
474 - .n_type = EBN_BOOTLOADER_NAME,
475 - },
476 - .bl_desc = BOOTLOADER,
477 - .blv_hdr = {
478 - .n_namesz = 0,
479 - .n_descsz = sizeof(BOOTLOADER_VERSION),
480 - .n_type = EBN_BOOTLOADER_VERSION,
481 - },
482 - .blv_desc = BOOTLOADER_VERSION,
483 - .cmd_hdr = {
484 - .n_namesz = 0,
485 - .n_descsz = 0,
486 - .n_type = EBN_COMMAND_LINE,
487 - },
488 -};
489 -
490 -
491 -#define OPT_APPEND (OPT_ARCH_MAX+0)
492 +/* 'kexec' in cmdline is used to find cmdline buffer by kernel */
493 +static char cmdline_buf[256] = "kexec ";
494
495 int elf_mips_probe(const char *buf, off_t len)
496 {
497 @@ -108,16 +75,14 @@ int elf_mips_load(int argc, char **argv,
498 struct kexec_info *info)
499 {
500 struct mem_ehdr ehdr;
501 - char *arg_buf;
502 - size_t arg_bytes;
503 - unsigned long arg_base;
504 - struct boot_notes *notes;
505 - size_t note_bytes;
506 - const char *command_line;
507 - int command_line_len;
508 - unsigned char *setup_start;
509 - uint32_t setup_size;
510 + unsigned long bss_start, bss_size = 0;
511 + const char *command_line = NULL;
512 + char *modified_cmdline;
513 + int modified_cmdline_len;
514 + unsigned long cmdline_addr;
515 + int result,i;
516 int opt;
517 +#define OPT_APPEND (OPT_ARCH_MAX+0)
518 static const struct option options[] = {
519 KEXEC_ARCH_OPTIONS
520 {"command-line", 1, 0, OPT_APPEND},
521 @@ -144,38 +109,81 @@ int elf_mips_load(int argc, char **argv,
522 break;
523 }
524 }
525 - command_line_len = 0;
526 - setup_simple_regs.spr9 = 0;
527 - if (command_line) {
528 - command_line_len = strlen(command_line) + 1;
529 - setup_simple_regs.spr9 = 2;
530 + /* Need to append some command line parameters internally in case of
531 + * taking crash dumps.
532 + */
533 + if (info->kexec_flags & KEXEC_ON_CRASH) {
534 + modified_cmdline = xmalloc(COMMAND_LINE_SIZE);
535 + memset((void *)modified_cmdline, 0, COMMAND_LINE_SIZE);
536 + if (command_line) {
537 + strncpy(modified_cmdline, command_line, COMMAND_LINE_SIZE);
538 + modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0';
539 + }
540 + modified_cmdline_len = strlen(modified_cmdline);
541 }
542
543 - /* Load the ELF executable */
544 - elf_exec_build_load(info, &ehdr, buf, len, 0);
545 -
546 - setup_start = setup_simple_start;
547 - setup_size = setup_simple_size;
548 - setup_simple_regs.spr8 = ehdr.e_entry;
549 -
550 - note_bytes = sizeof(elf_boot_notes) + ((command_line_len + 3) & ~3);
551 - arg_bytes = note_bytes + ((setup_size + 3) & ~3);
552 -
553 - arg_buf = xmalloc(arg_bytes);
554 - arg_base = add_buffer_virt(info,
555 - arg_buf, arg_bytes, arg_bytes, 4, 0, elf_max_addr(&ehdr), 1);
556 + /* Parse the Elf file */
557 + result = build_elf_exec_info(buf, len, &ehdr, 0);
558 + if (result < 0) {
559 + die("ELF exec parse failed\n");
560 + }
561
562 - notes = (struct boot_notes *)(arg_buf + ((setup_size + 3) & ~3));
563 + /* Read in the PT_LOAD segments and remove CKSEG0 mask from address*/
564 + for(i = 0; i < ehdr.e_phnum; i++) {
565 + struct mem_phdr *phdr;
566 + phdr = &ehdr.e_phdr[i];
567 + if (phdr->p_type == PT_LOAD) {
568 + phdr->p_paddr = virt_to_phys(phdr->p_paddr);
569 + }
570 + }
571
572 - memcpy(arg_buf, setup_start, setup_size);
573 - memcpy(notes, &elf_boot_notes, sizeof(elf_boot_notes));
574 - memcpy(notes->command_line, command_line, command_line_len);
575 + for(i = 0; i < ehdr.e_shnum; i++) {
576 + struct mem_shdr *shdr;
577 + unsigned char *strtab;
578 + strtab = (unsigned char *)ehdr.e_shdr[ehdr.e_shstrndx].sh_data;
579 +
580 + shdr = &ehdr.e_shdr[i];
581 + if ( shdr->sh_size &&
582 + strcmp((char *)&strtab[shdr->sh_name],
583 + ".bss") == 0) {
584 + bss_start = virt_to_phys(shdr->sh_addr);
585 + bss_size = shdr->sh_size;
586 + break;
587 + }
588 + }
589
590 - notes->hdr.b_size = note_bytes;
591 - notes->cmd_hdr.n_descsz = command_line_len;
592 - notes->hdr.b_checksum = compute_ip_checksum(notes, note_bytes);
593 + /* Load the Elf data */
594 + result = elf_exec_load(&ehdr, info);
595 + if (result < 0) {
596 + die("ELF exec load failed\n");
597 + }
598 + info->entry = (void *)virt_to_phys(ehdr.e_entry);
599 + if(!bss_size)
600 + die("No .bss segment present\n");
601 +
602 + /* Put cmdline right after bss */
603 + cmdline_addr = bss_start + bss_size;
604 +
605 + /* If panic kernel is being loaded, additional segments need
606 + * to be created.
607 + */
608 + if (info->kexec_flags & KEXEC_ON_CRASH) {
609 + result = load_crashdump_segments(info, modified_cmdline,
610 + 0, 0);
611 + if (result < 0)
612 + return -1;
613 + /* Use new command line. */
614 + command_line = modified_cmdline;
615 + }
616
617 - info->entry = (void *)arg_base;
618 + if (command_line)
619 + {
620 + strncat(cmdline_buf,command_line,
621 + sizeof(cmdline_buf) - strlen(cmdline_buf) - 1);
622 + add_buffer(info, cmdline_buf, sizeof(cmdline_buf),
623 + sizeof(cmdline_buf), sizeof(void*),
624 + cmdline_addr, 0x0fffffff, 1);
625 + }
626
627 return 0;
628 }
629 --- a/kexec/arch/mips/kexec-mips.c
630 +++ b/kexec/arch/mips/kexec-mips.c
631 @@ -97,8 +97,18 @@ int file_types = sizeof(file_type) / siz
632
633 void arch_usage(void)
634 {
635 +#ifdef __mips64
636 + fprintf(stderr, " --elf32-core-headers Prepare core headers in "
637 + "ELF32 format\n");
638 +#endif
639 }
640
641 +#ifdef __mips64
642 +struct arch_options_t arch_options = {
643 + .core_header_type = CORE_TYPE_ELF64
644 +};
645 +#endif
646 +
647 int arch_process_options(int argc, char **argv)
648 {
649 static const struct option options[] = {
650 @@ -113,6 +123,11 @@ int arch_process_options(int argc, char
651 switch(opt) {
652 default:
653 break;
654 +#ifdef __mips64
655 + case OPT_ELF64_CORE:
656 + arch_options.core_header_type = CORE_TYPE_ELF64;
657 + break;
658 +#endif
659 }
660 }
661 /* Reset getopt for the next pass; called in other source modules */
662 @@ -126,6 +141,10 @@ const struct arch_map_entry arches[] = {
663 * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_MIPS here.
664 */
665 { "mips", KEXEC_ARCH_DEFAULT },
666 + /* Not using KEXEC_ARCH_DEFAULT because that will fail
667 + * in the kernel's compat_sys_kexec_load() routine.
668 + */
669 + { "mips64", KEXEC_ARCH_MIPS },
670 { 0 },
671 };
672
673 @@ -138,18 +157,9 @@ void arch_update_purgatory(struct kexec_
674 {
675 }
676
677 -/*
678 - * Adding a dummy function, so that build on mips will not break.
679 - * Need to implement the actual checking code
680 - */
681 -int is_crashkernel_mem_reserved(void)
682 -{
683 - return 1;
684 -}
685 -
686 unsigned long virt_to_phys(unsigned long addr)
687 {
688 - return addr - 0x80000000;
689 + return ((addr)& 0x7fffffff);
690 }
691
692 /*
693 --- a/kexec/arch/mips/kexec-mips.h
694 +++ b/kexec/arch/mips/kexec-mips.h
695 @@ -1,17 +1,16 @@
696 #ifndef KEXEC_MIPS_H
697 #define KEXEC_MIPS_H
698
699 -extern unsigned char setup_simple_start[];
700 -extern uint32_t setup_simple_size;
701 -
702 -extern struct {
703 - uint32_t spr8;
704 - uint32_t spr9;
705 -} setup_simple_regs;
706 +#define MAX_MEMORY_RANGES 64
707 +#define CORE_TYPE_ELF32 1
708 +#define CORE_TYPE_ELF64 2
709
710 int elf_mips_probe(const char *buf, off_t len);
711 int elf_mips_load(int argc, char **argv, const char *buf, off_t len,
712 struct kexec_info *info);
713 void elf_mips_usage(void);
714
715 +struct arch_options_t {
716 + int core_header_type;
717 +};
718 #endif /* KEXEC_MIPS_H */