Skip to content

Commit cbded96

Browse files
author
Mamatha Inamdar
committed
powerpc/fadump: setup additional parameters for dump capture kernel
JIRA: https://issues.redhat.com/browse/RHEL-52914 commit 683eab9 Author: Hari Bathini <hbathini@linux.ibm.com> Date: Thu May 9 17:27:54 2024 +0530 powerpc/fadump: setup additional parameters for dump capture kernel For fadump case, passing additional parameters to dump capture kernel helps in minimizing the memory footprint for it and also provides the flexibility to disable components/modules, like hugepages, that are hindering the boot process of the special dump capture environment. Set up a dedicated parameter area to be passed to the capture kernel. This area type is defined as RTAS_FADUMP_PARAM_AREA. Sysfs attribute '/sys/kernel/fadump/bootargs_append' is exported to the userspace to specify the additional parameters to be passed to the capture kernel Signed-off-by: Hari Bathini <hbathini@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://msgid.link/20240509115755.519982-3-hbathini@linux.ibm.com Signed-off-by: Mamatha Inamdar <minamdar@redhat.com>
1 parent 1f1adfd commit cbded96

File tree

5 files changed

+135
-10
lines changed

5 files changed

+135
-10
lines changed

arch/powerpc/include/asm/fadump-internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ struct fw_dump {
9797
unsigned long cpu_notes_buf_vaddr;
9898
unsigned long cpu_notes_buf_size;
9999

100+
unsigned long param_area;
101+
100102
/*
101103
* Maximum size supported by firmware to copy from source to
102104
* destination address per entry.
@@ -111,6 +113,7 @@ struct fw_dump {
111113
unsigned long dump_active:1;
112114
unsigned long dump_registered:1;
113115
unsigned long nocma:1;
116+
unsigned long param_area_supported:1;
114117

115118
struct fadump_ops *ops;
116119
};

arch/powerpc/kernel/fadump.c

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1477,6 +1477,43 @@ static ssize_t registered_show(struct kobject *kobj,
14771477
return sprintf(buf, "%d\n", fw_dump.dump_registered);
14781478
}
14791479

1480+
static ssize_t bootargs_append_show(struct kobject *kobj,
1481+
struct kobj_attribute *attr,
1482+
char *buf)
1483+
{
1484+
return sprintf(buf, "%s\n", (char *)__va(fw_dump.param_area));
1485+
}
1486+
1487+
static ssize_t bootargs_append_store(struct kobject *kobj,
1488+
struct kobj_attribute *attr,
1489+
const char *buf, size_t count)
1490+
{
1491+
char *params;
1492+
1493+
if (!fw_dump.fadump_enabled || fw_dump.dump_active)
1494+
return -EPERM;
1495+
1496+
if (count >= COMMAND_LINE_SIZE)
1497+
return -EINVAL;
1498+
1499+
/*
1500+
* Fail here instead of handling this scenario with
1501+
* some silly workaround in capture kernel.
1502+
*/
1503+
if (strlen(saved_command_line) + count >= COMMAND_LINE_SIZE) {
1504+
pr_err("Appending parameters exceeds cmdline size!\n");
1505+
return -ENOSPC;
1506+
}
1507+
1508+
params = __va(fw_dump.param_area);
1509+
strscpy_pad(params, buf, COMMAND_LINE_SIZE);
1510+
/* Remove newline character at the end. */
1511+
if (params[count-1] == '\n')
1512+
params[count-1] = '\0';
1513+
1514+
return count;
1515+
}
1516+
14801517
static ssize_t registered_store(struct kobject *kobj,
14811518
struct kobj_attribute *attr,
14821519
const char *buf, size_t count)
@@ -1535,6 +1572,7 @@ static struct kobj_attribute release_attr = __ATTR_WO(release_mem);
15351572
static struct kobj_attribute enable_attr = __ATTR_RO(enabled);
15361573
static struct kobj_attribute register_attr = __ATTR_RW(registered);
15371574
static struct kobj_attribute mem_reserved_attr = __ATTR_RO(mem_reserved);
1575+
static struct kobj_attribute bootargs_append_attr = __ATTR_RW(bootargs_append);
15381576

15391577
static struct attribute *fadump_attrs[] = {
15401578
&enable_attr.attr,
@@ -1611,6 +1649,54 @@ static void __init fadump_init_files(void)
16111649
return;
16121650
}
16131651

1652+
/*
1653+
* Reserve memory to store additional parameters to be passed
1654+
* for fadump/capture kernel.
1655+
*/
1656+
static void fadump_setup_param_area(void)
1657+
{
1658+
phys_addr_t range_start, range_end;
1659+
1660+
if (!fw_dump.param_area_supported || fw_dump.dump_active)
1661+
return;
1662+
1663+
/* This memory can't be used by PFW or bootloader as it is shared across kernels */
1664+
if (radix_enabled()) {
1665+
/*
1666+
* Anywhere in the upper half should be good enough as all memory
1667+
* is accessible in real mode.
1668+
*/
1669+
range_start = memblock_end_of_DRAM() / 2;
1670+
range_end = memblock_end_of_DRAM();
1671+
} else {
1672+
/*
1673+
* Passing additional parameters is supported for hash MMU only
1674+
* if the first memory block size is 768MB or higher.
1675+
*/
1676+
if (ppc64_rma_size < 0x30000000)
1677+
return;
1678+
1679+
/*
1680+
* 640 MB to 768 MB is not used by PFW/bootloader. So, try reserving
1681+
* memory for passing additional parameters in this range to avoid
1682+
* being stomped on by PFW/bootloader.
1683+
*/
1684+
range_start = 0x2A000000;
1685+
range_end = range_start + 0x4000000;
1686+
}
1687+
1688+
fw_dump.param_area = memblock_phys_alloc_range(COMMAND_LINE_SIZE,
1689+
COMMAND_LINE_SIZE,
1690+
range_start,
1691+
range_end);
1692+
if (!fw_dump.param_area || sysfs_create_file(fadump_kobj, &bootargs_append_attr.attr)) {
1693+
pr_warn("WARNING: Could not setup area to pass additional parameters!\n");
1694+
return;
1695+
}
1696+
1697+
memset(phys_to_virt(fw_dump.param_area), 0, COMMAND_LINE_SIZE);
1698+
}
1699+
16141700
/*
16151701
* Prepare for firmware-assisted dump.
16161702
*/
@@ -1638,8 +1724,10 @@ int __init setup_fadump(void)
16381724
fadump_invalidate_release_mem();
16391725
}
16401726
/* Initialize the kernel dump memory structure for FAD registration. */
1641-
else if (fw_dump.reserve_dump_area_size)
1727+
else if (fw_dump.reserve_dump_area_size) {
1728+
fadump_setup_param_area();
16421729
fw_dump.ops->fadump_init_mem_struct(&fw_dump);
1730+
}
16431731

16441732
/*
16451733
* In case of panic, fadump is triggered via ppc_panic_event()

arch/powerpc/platforms/powernv/opal-fadump.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -671,8 +671,10 @@ void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
671671
}
672672
}
673673

674-
fadump_conf->ops = &opal_fadump_ops;
675-
fadump_conf->fadump_supported = 1;
674+
fadump_conf->ops = &opal_fadump_ops;
675+
fadump_conf->fadump_supported = 1;
676+
/* TODO: Add support to pass additional parameters */
677+
fadump_conf->param_area_supported = 0;
676678

677679
/*
678680
* Firmware supports 32-bit field for size. Align it to PAGE_SIZE

arch/powerpc/platforms/pseries/rtas-fadump.c

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <asm/page.h>
2020
#include <asm/rtas.h>
21+
#include <asm/setup.h>
2122
#include <asm/fadump.h>
2223
#include <asm/fadump-internal.h>
2324

@@ -81,6 +82,9 @@ static void rtas_fadump_get_config(struct fw_dump *fadump_conf,
8182
last_end = base + size;
8283
fadump_conf->boot_mem_regs_cnt++;
8384
break;
85+
case RTAS_FADUMP_PARAM_AREA:
86+
fadump_conf->param_area = be64_to_cpu(fdm->rgn[i].destination_address);
87+
break;
8488
default:
8589
pr_warn("Section type %d unsupported on this kernel. Ignoring!\n", type);
8690
break;
@@ -154,7 +158,17 @@ static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf)
154158
sec_cnt++;
155159
}
156160

161+
/* Parameters area */
162+
if (fadump_conf->param_area) {
163+
fdm.rgn[sec_cnt].request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
164+
fdm.rgn[sec_cnt].source_data_type = cpu_to_be16(RTAS_FADUMP_PARAM_AREA);
165+
fdm.rgn[sec_cnt].source_address = cpu_to_be64(fadump_conf->param_area);
166+
fdm.rgn[sec_cnt].source_len = cpu_to_be64(COMMAND_LINE_SIZE);
167+
fdm.rgn[sec_cnt].destination_address = cpu_to_be64(fadump_conf->param_area);
168+
sec_cnt++;
169+
}
157170
fdm.header.dump_num_sections = cpu_to_be16(sec_cnt);
171+
158172
rtas_fadump_update_config(fadump_conf, &fdm);
159173

160174
return addr;
@@ -459,6 +473,13 @@ static int __init rtas_fadump_process(struct fw_dump *fadump_conf)
459473
return rc;
460474
}
461475
break;
476+
case RTAS_FADUMP_PARAM_AREA:
477+
if (fdm_active->rgn[i].bytes_dumped != fdm_active->rgn[i].source_len ||
478+
fdm_active->rgn[i].error_flags != 0) {
479+
pr_warn("Failed to process additional parameters! Proceeding anyway..\n");
480+
fadump_conf->param_area = 0;
481+
}
482+
break;
462483
default:
463484
/*
464485
* If the first/crashed kernel added a new region type that the
@@ -533,6 +554,13 @@ static void rtas_fadump_region_show(struct fw_dump *fadump_conf,
533554
be64_to_cpu(fdm_ptr->rgn[i].source_len),
534555
be64_to_cpu(fdm_ptr->rgn[i].bytes_dumped));
535556
break;
557+
case RTAS_FADUMP_PARAM_AREA:
558+
seq_printf(m, "\n[%#016llx-%#016llx]: cmdline append: '%s'\n",
559+
be64_to_cpu(fdm_ptr->rgn[i].destination_address),
560+
be64_to_cpu(fdm_ptr->rgn[i].destination_address) +
561+
be64_to_cpu(fdm_ptr->rgn[i].source_len) - 1,
562+
(char *)__va(be64_to_cpu(fdm_ptr->rgn[i].destination_address)));
563+
break;
536564
default:
537565
seq_printf(m, "Unknown region type %d : Src: %#016llx, Dest: %#016llx, ",
538566
type, be64_to_cpu(fdm_ptr->rgn[i].source_address),
@@ -595,9 +623,10 @@ void __init rtas_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
595623
if (!token)
596624
return;
597625

598-
fadump_conf->ibm_configure_kernel_dump = be32_to_cpu(*token);
599-
fadump_conf->ops = &rtas_fadump_ops;
600-
fadump_conf->fadump_supported = 1;
626+
fadump_conf->ibm_configure_kernel_dump = be32_to_cpu(*token);
627+
fadump_conf->ops = &rtas_fadump_ops;
628+
fadump_conf->fadump_supported = 1;
629+
fadump_conf->param_area_supported = 1;
601630

602631
/* Firmware supports 64-bit value for size, align it to pagesize. */
603632
fadump_conf->max_copy_size = ALIGN_DOWN(U64_MAX, PAGE_SIZE);

arch/powerpc/platforms/pseries/rtas-fadump.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
#define RTAS_FADUMP_HPTE_REGION 0x0002
2424
#define RTAS_FADUMP_REAL_MODE_REGION 0x0011
2525

26+
/* OS defined sections */
27+
#define RTAS_FADUMP_PARAM_AREA 0x0100
28+
2629
/* Dump request flag */
2730
#define RTAS_FADUMP_REQUEST_FLAG 0x00000001
2831

@@ -31,12 +34,12 @@
3134

3235
/*
3336
* The Firmware Assisted Dump Memory structure supports a maximum of 10 sections
34-
* in the dump memory structure. Presently, first two sections are used for
35-
* CPU and HPTE data, while the remaining eight sections can be used for
36-
* boot memory regions.
37+
* in the dump memory structure. Presently, three sections are used for
38+
* CPU state data, HPTE & Parameters area, while the remaining seven sections
39+
* can be used for boot memory regions.
3740
*/
3841
#define MAX_SECTIONS 10
39-
#define RTAS_FADUMP_MAX_BOOT_MEM_REGS 8
42+
#define RTAS_FADUMP_MAX_BOOT_MEM_REGS 7
4043

4144
/* Kernel Dump section info */
4245
struct rtas_fadump_section {

0 commit comments

Comments
 (0)