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 */ |
|