ranges.c (79790b6818e96c58fe2bffee1b418c16e64e7b80) ranges.c (f5f0da5a7b18fab383bac92044fd8f4f288c9d38)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * powerpc code to implement the kexec_file_load syscall
4 *
5 * Copyright (C) 2004 Adam Litke (agl@us.ibm.com)
6 * Copyright (C) 2004 IBM Corp.
7 * Copyright (C) 2004,2005 Milton D Miller II, IBM Corporation
8 * Copyright (C) 2005 R Sharada (sharada@in.ibm.com)

--- 6 unchanged lines hidden (view full) ---

15 */
16
17#define pr_fmt(fmt) "kexec ranges: " fmt
18
19#include <linux/sort.h>
20#include <linux/kexec.h>
21#include <linux/of.h>
22#include <linux/slab.h>
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * powerpc code to implement the kexec_file_load syscall
4 *
5 * Copyright (C) 2004 Adam Litke (agl@us.ibm.com)
6 * Copyright (C) 2004 IBM Corp.
7 * Copyright (C) 2004,2005 Milton D Miller II, IBM Corporation
8 * Copyright (C) 2005 R Sharada (sharada@in.ibm.com)

--- 6 unchanged lines hidden (view full) ---

15 */
16
17#define pr_fmt(fmt) "kexec ranges: " fmt
18
19#include <linux/sort.h>
20#include <linux/kexec.h>
21#include <linux/of.h>
22#include <linux/slab.h>
23#include <linux/memblock.h>
24#include <linux/crash_core.h>
23#include <asm/sections.h>
24#include <asm/kexec_ranges.h>
25#include <asm/sections.h>
26#include <asm/kexec_ranges.h>
27#include <asm/crashdump-ppc64.h>
25
28
29#if defined(CONFIG_KEXEC_FILE) || defined(CONFIG_CRASH_DUMP)
26/**
27 * get_max_nr_ranges - Get the max no. of ranges crash_mem structure
28 * could hold, given the size allocated for it.
29 * @size: Allocation size of crash_mem structure.
30 *
31 * Returns the maximum no. of ranges.
32 */
33static inline unsigned int get_max_nr_ranges(size_t size)

--- 195 unchanged lines hidden (view full) ---

229 mem_rngs->ranges[i].end = end;
230 return 0;
231 }
232 }
233
234 return __add_mem_range(mem_ranges, base, size);
235}
236
30/**
31 * get_max_nr_ranges - Get the max no. of ranges crash_mem structure
32 * could hold, given the size allocated for it.
33 * @size: Allocation size of crash_mem structure.
34 *
35 * Returns the maximum no. of ranges.
36 */
37static inline unsigned int get_max_nr_ranges(size_t size)

--- 195 unchanged lines hidden (view full) ---

233 mem_rngs->ranges[i].end = end;
234 return 0;
235 }
236 }
237
238 return __add_mem_range(mem_ranges, base, size);
239}
240
241#endif /* CONFIG_KEXEC_FILE || CONFIG_CRASH_DUMP */
242
243#ifdef CONFIG_KEXEC_FILE
237/**
238 * add_tce_mem_ranges - Adds tce-table range to the given memory ranges list.
239 * @mem_ranges: Range list to add the memory range(s) to.
240 *
241 * Returns 0 on success, negative errno on error.
242 */
244/**
245 * add_tce_mem_ranges - Adds tce-table range to the given memory ranges list.
246 * @mem_ranges: Range list to add the memory range(s) to.
247 *
248 * Returns 0 on success, negative errno on error.
249 */
243int add_tce_mem_ranges(struct crash_mem **mem_ranges)
250static int add_tce_mem_ranges(struct crash_mem **mem_ranges)
244{
245 struct device_node *dn = NULL;
246 int ret = 0;
247
248 for_each_node_by_type(dn, "pci") {
249 u64 base;
250 u32 size;
251

--- 22 unchanged lines hidden (view full) ---

274
275/**
276 * add_initrd_mem_range - Adds initrd range to the given memory ranges list,
277 * if the initrd was retained.
278 * @mem_ranges: Range list to add the memory range to.
279 *
280 * Returns 0 on success, negative errno on error.
281 */
251{
252 struct device_node *dn = NULL;
253 int ret = 0;
254
255 for_each_node_by_type(dn, "pci") {
256 u64 base;
257 u32 size;
258

--- 22 unchanged lines hidden (view full) ---

281
282/**
283 * add_initrd_mem_range - Adds initrd range to the given memory ranges list,
284 * if the initrd was retained.
285 * @mem_ranges: Range list to add the memory range to.
286 *
287 * Returns 0 on success, negative errno on error.
288 */
282int add_initrd_mem_range(struct crash_mem **mem_ranges)
289static int add_initrd_mem_range(struct crash_mem **mem_ranges)
283{
284 u64 base, end;
285 int ret;
286
287 /* This range means something, only if initrd was retained */
288 if (!strstr(saved_command_line, "retain_initrd"))
289 return 0;
290
291 ret = of_property_read_u64(of_chosen, "linux,initrd-start", &base);
292 ret |= of_property_read_u64(of_chosen, "linux,initrd-end", &end);
293 if (!ret)
294 ret = add_mem_range(mem_ranges, base, end - base + 1);
295
296 return ret;
297}
298
290{
291 u64 base, end;
292 int ret;
293
294 /* This range means something, only if initrd was retained */
295 if (!strstr(saved_command_line, "retain_initrd"))
296 return 0;
297
298 ret = of_property_read_u64(of_chosen, "linux,initrd-start", &base);
299 ret |= of_property_read_u64(of_chosen, "linux,initrd-end", &end);
300 if (!ret)
301 ret = add_mem_range(mem_ranges, base, end - base + 1);
302
303 return ret;
304}
305
299#ifdef CONFIG_PPC_64S_HASH_MMU
300/**
301 * add_htab_mem_range - Adds htab range to the given memory ranges list,
302 * if it exists
303 * @mem_ranges: Range list to add the memory range to.
304 *
305 * Returns 0 on success, negative errno on error.
306 */
306/**
307 * add_htab_mem_range - Adds htab range to the given memory ranges list,
308 * if it exists
309 * @mem_ranges: Range list to add the memory range to.
310 *
311 * Returns 0 on success, negative errno on error.
312 */
307int add_htab_mem_range(struct crash_mem **mem_ranges)
313static int add_htab_mem_range(struct crash_mem **mem_ranges)
308{
314{
315
316#ifdef CONFIG_PPC_64S_HASH_MMU
309 if (!htab_address)
310 return 0;
311
312 return add_mem_range(mem_ranges, __pa(htab_address), htab_size_bytes);
317 if (!htab_address)
318 return 0;
319
320 return add_mem_range(mem_ranges, __pa(htab_address), htab_size_bytes);
313}
321#else
322 return 0;
314#endif
323#endif
324}
315
316/**
317 * add_kernel_mem_range - Adds kernel text region to the given
318 * memory ranges list.
319 * @mem_ranges: Range list to add the memory range to.
320 *
321 * Returns 0 on success, negative errno on error.
322 */
325
326/**
327 * add_kernel_mem_range - Adds kernel text region to the given
328 * memory ranges list.
329 * @mem_ranges: Range list to add the memory range to.
330 *
331 * Returns 0 on success, negative errno on error.
332 */
323int add_kernel_mem_range(struct crash_mem **mem_ranges)
333static int add_kernel_mem_range(struct crash_mem **mem_ranges)
324{
325 return add_mem_range(mem_ranges, 0, __pa(_end));
326}
334{
335 return add_mem_range(mem_ranges, 0, __pa(_end));
336}
337#endif /* CONFIG_KEXEC_FILE */
327
338
339#if defined(CONFIG_KEXEC_FILE) || defined(CONFIG_CRASH_DUMP)
328/**
329 * add_rtas_mem_range - Adds RTAS region to the given memory ranges list.
330 * @mem_ranges: Range list to add the memory range to.
331 *
332 * Returns 0 on success, negative errno on error.
333 */
340/**
341 * add_rtas_mem_range - Adds RTAS region to the given memory ranges list.
342 * @mem_ranges: Range list to add the memory range to.
343 *
344 * Returns 0 on success, negative errno on error.
345 */
334int add_rtas_mem_range(struct crash_mem **mem_ranges)
346static int add_rtas_mem_range(struct crash_mem **mem_ranges)
335{
336 struct device_node *dn;
337 u32 base, size;
338 int ret = 0;
339
340 dn = of_find_node_by_path("/rtas");
341 if (!dn)
342 return 0;

--- 8 unchanged lines hidden (view full) ---

351}
352
353/**
354 * add_opal_mem_range - Adds OPAL region to the given memory ranges list.
355 * @mem_ranges: Range list to add the memory range to.
356 *
357 * Returns 0 on success, negative errno on error.
358 */
347{
348 struct device_node *dn;
349 u32 base, size;
350 int ret = 0;
351
352 dn = of_find_node_by_path("/rtas");
353 if (!dn)
354 return 0;

--- 8 unchanged lines hidden (view full) ---

363}
364
365/**
366 * add_opal_mem_range - Adds OPAL region to the given memory ranges list.
367 * @mem_ranges: Range list to add the memory range to.
368 *
369 * Returns 0 on success, negative errno on error.
370 */
359int add_opal_mem_range(struct crash_mem **mem_ranges)
371static int add_opal_mem_range(struct crash_mem **mem_ranges)
360{
361 struct device_node *dn;
362 u64 base, size;
363 int ret;
364
365 dn = of_find_node_by_path("/ibm,opal");
366 if (!dn)
367 return 0;
368
369 ret = of_property_read_u64(dn, "opal-base-address", &base);
370 ret |= of_property_read_u64(dn, "opal-runtime-size", &size);
371 if (!ret)
372 ret = add_mem_range(mem_ranges, base, size);
373
374 of_node_put(dn);
375 return ret;
376}
372{
373 struct device_node *dn;
374 u64 base, size;
375 int ret;
376
377 dn = of_find_node_by_path("/ibm,opal");
378 if (!dn)
379 return 0;
380
381 ret = of_property_read_u64(dn, "opal-base-address", &base);
382 ret |= of_property_read_u64(dn, "opal-runtime-size", &size);
383 if (!ret)
384 ret = add_mem_range(mem_ranges, base, size);
385
386 of_node_put(dn);
387 return ret;
388}
389#endif /* CONFIG_KEXEC_FILE || CONFIG_CRASH_DUMP */
377
390
391#ifdef CONFIG_KEXEC_FILE
378/**
379 * add_reserved_mem_ranges - Adds "/reserved-ranges" regions exported by f/w
380 * to the given memory ranges list.
381 * @mem_ranges: Range list to add the memory ranges to.
382 *
383 * Returns 0 on success, negative errno on error.
384 */
392/**
393 * add_reserved_mem_ranges - Adds "/reserved-ranges" regions exported by f/w
394 * to the given memory ranges list.
395 * @mem_ranges: Range list to add the memory ranges to.
396 *
397 * Returns 0 on success, negative errno on error.
398 */
385int add_reserved_mem_ranges(struct crash_mem **mem_ranges)
399static int add_reserved_mem_ranges(struct crash_mem **mem_ranges)
386{
387 int n_mem_addr_cells, n_mem_size_cells, i, len, cells, ret = 0;
388 struct device_node *root = of_find_node_by_path("/");
389 const __be32 *prop;
390
391 prop = of_get_property(root, "reserved-ranges", &len);
392 n_mem_addr_cells = of_n_addr_cells(root);
393 n_mem_size_cells = of_n_size_cells(root);

--- 13 unchanged lines hidden (view full) ---

407
408 ret = add_mem_range(mem_ranges, base, size);
409 if (ret)
410 break;
411 }
412
413 return ret;
414}
400{
401 int n_mem_addr_cells, n_mem_size_cells, i, len, cells, ret = 0;
402 struct device_node *root = of_find_node_by_path("/");
403 const __be32 *prop;
404
405 prop = of_get_property(root, "reserved-ranges", &len);
406 n_mem_addr_cells = of_n_addr_cells(root);
407 n_mem_size_cells = of_n_size_cells(root);

--- 13 unchanged lines hidden (view full) ---

421
422 ret = add_mem_range(mem_ranges, base, size);
423 if (ret)
424 break;
425 }
426
427 return ret;
428}
429
430/**
431 * get_reserved_memory_ranges - Get reserve memory ranges. This list includes
432 * memory regions that should be added to the
433 * memory reserve map to ensure the region is
434 * protected from any mischief.
435 * @mem_ranges: Range list to add the memory ranges to.
436 *
437 * Returns 0 on success, negative errno on error.
438 */
439int get_reserved_memory_ranges(struct crash_mem **mem_ranges)
440{
441 int ret;
442
443 ret = add_rtas_mem_range(mem_ranges);
444 if (ret)
445 goto out;
446
447 ret = add_tce_mem_ranges(mem_ranges);
448 if (ret)
449 goto out;
450
451 ret = add_reserved_mem_ranges(mem_ranges);
452out:
453 if (ret)
454 pr_err("Failed to setup reserved memory ranges\n");
455 return ret;
456}
457
458/**
459 * get_exclude_memory_ranges - Get exclude memory ranges. This list includes
460 * regions like opal/rtas, tce-table, initrd,
461 * kernel, htab which should be avoided while
462 * setting up kexec load segments.
463 * @mem_ranges: Range list to add the memory ranges to.
464 *
465 * Returns 0 on success, negative errno on error.
466 */
467int get_exclude_memory_ranges(struct crash_mem **mem_ranges)
468{
469 int ret;
470
471 ret = add_tce_mem_ranges(mem_ranges);
472 if (ret)
473 goto out;
474
475 ret = add_initrd_mem_range(mem_ranges);
476 if (ret)
477 goto out;
478
479 ret = add_htab_mem_range(mem_ranges);
480 if (ret)
481 goto out;
482
483 ret = add_kernel_mem_range(mem_ranges);
484 if (ret)
485 goto out;
486
487 ret = add_rtas_mem_range(mem_ranges);
488 if (ret)
489 goto out;
490
491 ret = add_opal_mem_range(mem_ranges);
492 if (ret)
493 goto out;
494
495 ret = add_reserved_mem_ranges(mem_ranges);
496 if (ret)
497 goto out;
498
499 /* exclude memory ranges should be sorted for easy lookup */
500 sort_memory_ranges(*mem_ranges, true);
501out:
502 if (ret)
503 pr_err("Failed to setup exclude memory ranges\n");
504 return ret;
505}
506
507#ifdef CONFIG_CRASH_DUMP
508/**
509 * get_usable_memory_ranges - Get usable memory ranges. This list includes
510 * regions like crashkernel, opal/rtas & tce-table,
511 * that kdump kernel could use.
512 * @mem_ranges: Range list to add the memory ranges to.
513 *
514 * Returns 0 on success, negative errno on error.
515 */
516int get_usable_memory_ranges(struct crash_mem **mem_ranges)
517{
518 int ret;
519
520 /*
521 * Early boot failure observed on guests when low memory (first memory
522 * block?) is not added to usable memory. So, add [0, crashk_res.end]
523 * instead of [crashk_res.start, crashk_res.end] to workaround it.
524 * Also, crashed kernel's memory must be added to reserve map to
525 * avoid kdump kernel from using it.
526 */
527 ret = add_mem_range(mem_ranges, 0, crashk_res.end + 1);
528 if (ret)
529 goto out;
530
531 ret = add_rtas_mem_range(mem_ranges);
532 if (ret)
533 goto out;
534
535 ret = add_opal_mem_range(mem_ranges);
536 if (ret)
537 goto out;
538
539 ret = add_tce_mem_ranges(mem_ranges);
540out:
541 if (ret)
542 pr_err("Failed to setup usable memory ranges\n");
543 return ret;
544}
545#endif /* CONFIG_CRASH_DUMP */
546#endif /* CONFIG_KEXEC_FILE */
547
548#ifdef CONFIG_CRASH_DUMP
549/**
550 * get_crash_memory_ranges - Get crash memory ranges. This list includes
551 * first/crashing kernel's memory regions that
552 * would be exported via an elfcore.
553 * @mem_ranges: Range list to add the memory ranges to.
554 *
555 * Returns 0 on success, negative errno on error.
556 */
557int get_crash_memory_ranges(struct crash_mem **mem_ranges)
558{
559 phys_addr_t base, end;
560 struct crash_mem *tmem;
561 u64 i;
562 int ret;
563
564 for_each_mem_range(i, &base, &end) {
565 u64 size = end - base;
566
567 /* Skip backup memory region, which needs a separate entry */
568 if (base == BACKUP_SRC_START) {
569 if (size > BACKUP_SRC_SIZE) {
570 base = BACKUP_SRC_END + 1;
571 size -= BACKUP_SRC_SIZE;
572 } else
573 continue;
574 }
575
576 ret = add_mem_range(mem_ranges, base, size);
577 if (ret)
578 goto out;
579
580 /* Try merging adjacent ranges before reallocation attempt */
581 if ((*mem_ranges)->nr_ranges == (*mem_ranges)->max_nr_ranges)
582 sort_memory_ranges(*mem_ranges, true);
583 }
584
585 /* Reallocate memory ranges if there is no space to split ranges */
586 tmem = *mem_ranges;
587 if (tmem && (tmem->nr_ranges == tmem->max_nr_ranges)) {
588 tmem = realloc_mem_ranges(mem_ranges);
589 if (!tmem)
590 goto out;
591 }
592
593 /* Exclude crashkernel region */
594 ret = crash_exclude_mem_range(tmem, crashk_res.start, crashk_res.end);
595 if (ret)
596 goto out;
597
598 /*
599 * FIXME: For now, stay in parity with kexec-tools but if RTAS/OPAL
600 * regions are exported to save their context at the time of
601 * crash, they should actually be backed up just like the
602 * first 64K bytes of memory.
603 */
604 ret = add_rtas_mem_range(mem_ranges);
605 if (ret)
606 goto out;
607
608 ret = add_opal_mem_range(mem_ranges);
609 if (ret)
610 goto out;
611
612 /* create a separate program header for the backup region */
613 ret = add_mem_range(mem_ranges, BACKUP_SRC_START, BACKUP_SRC_SIZE);
614 if (ret)
615 goto out;
616
617 sort_memory_ranges(*mem_ranges, false);
618out:
619 if (ret)
620 pr_err("Failed to setup crash memory ranges\n");
621 return ret;
622}
623#endif /* CONFIG_CRASH_DUMP */