Skip to content

Commit 683eab9

Browse files
hbathinimpe
authored andcommitted
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 <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://msgid.link/[email protected]
1 parent 78d5cc1 commit 683eab9

File tree

5 files changed

+133
-9
lines changed

5 files changed

+133
-9
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ struct fw_dump {
124124
unsigned long cpu_notes_buf_vaddr;
125125
unsigned long cpu_notes_buf_size;
126126

127+
unsigned long param_area;
128+
127129
/*
128130
* Maximum size supported by firmware to copy from source to
129131
* destination address per entry.
@@ -138,6 +140,7 @@ struct fw_dump {
138140
unsigned long dump_active:1;
139141
unsigned long dump_registered:1;
140142
unsigned long nocma:1;
143+
unsigned long param_area_supported:1;
141144

142145
struct fadump_ops *ops;
143146
};

arch/powerpc/kernel/fadump.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,6 +1431,43 @@ static ssize_t registered_show(struct kobject *kobj,
14311431
return sprintf(buf, "%d\n", fw_dump.dump_registered);
14321432
}
14331433

1434+
static ssize_t bootargs_append_show(struct kobject *kobj,
1435+
struct kobj_attribute *attr,
1436+
char *buf)
1437+
{
1438+
return sprintf(buf, "%s\n", (char *)__va(fw_dump.param_area));
1439+
}
1440+
1441+
static ssize_t bootargs_append_store(struct kobject *kobj,
1442+
struct kobj_attribute *attr,
1443+
const char *buf, size_t count)
1444+
{
1445+
char *params;
1446+
1447+
if (!fw_dump.fadump_enabled || fw_dump.dump_active)
1448+
return -EPERM;
1449+
1450+
if (count >= COMMAND_LINE_SIZE)
1451+
return -EINVAL;
1452+
1453+
/*
1454+
* Fail here instead of handling this scenario with
1455+
* some silly workaround in capture kernel.
1456+
*/
1457+
if (saved_command_line_len + count >= COMMAND_LINE_SIZE) {
1458+
pr_err("Appending parameters exceeds cmdline size!\n");
1459+
return -ENOSPC;
1460+
}
1461+
1462+
params = __va(fw_dump.param_area);
1463+
strscpy_pad(params, buf, COMMAND_LINE_SIZE);
1464+
/* Remove newline character at the end. */
1465+
if (params[count-1] == '\n')
1466+
params[count-1] = '\0';
1467+
1468+
return count;
1469+
}
1470+
14341471
static ssize_t registered_store(struct kobject *kobj,
14351472
struct kobj_attribute *attr,
14361473
const char *buf, size_t count)
@@ -1490,6 +1527,7 @@ static struct kobj_attribute enable_attr = __ATTR_RO(enabled);
14901527
static struct kobj_attribute register_attr = __ATTR_RW(registered);
14911528
static struct kobj_attribute mem_reserved_attr = __ATTR_RO(mem_reserved);
14921529
static struct kobj_attribute hotplug_ready_attr = __ATTR_RO(hotplug_ready);
1530+
static struct kobj_attribute bootargs_append_attr = __ATTR_RW(bootargs_append);
14931531

14941532
static struct attribute *fadump_attrs[] = {
14951533
&enable_attr.attr,
@@ -1663,6 +1701,54 @@ static void __init fadump_process(void)
16631701
fadump_invalidate_release_mem();
16641702
}
16651703

1704+
/*
1705+
* Reserve memory to store additional parameters to be passed
1706+
* for fadump/capture kernel.
1707+
*/
1708+
static void fadump_setup_param_area(void)
1709+
{
1710+
phys_addr_t range_start, range_end;
1711+
1712+
if (!fw_dump.param_area_supported || fw_dump.dump_active)
1713+
return;
1714+
1715+
/* This memory can't be used by PFW or bootloader as it is shared across kernels */
1716+
if (radix_enabled()) {
1717+
/*
1718+
* Anywhere in the upper half should be good enough as all memory
1719+
* is accessible in real mode.
1720+
*/
1721+
range_start = memblock_end_of_DRAM() / 2;
1722+
range_end = memblock_end_of_DRAM();
1723+
} else {
1724+
/*
1725+
* Passing additional parameters is supported for hash MMU only
1726+
* if the first memory block size is 768MB or higher.
1727+
*/
1728+
if (ppc64_rma_size < 0x30000000)
1729+
return;
1730+
1731+
/*
1732+
* 640 MB to 768 MB is not used by PFW/bootloader. So, try reserving
1733+
* memory for passing additional parameters in this range to avoid
1734+
* being stomped on by PFW/bootloader.
1735+
*/
1736+
range_start = 0x2A000000;
1737+
range_end = range_start + 0x4000000;
1738+
}
1739+
1740+
fw_dump.param_area = memblock_phys_alloc_range(COMMAND_LINE_SIZE,
1741+
COMMAND_LINE_SIZE,
1742+
range_start,
1743+
range_end);
1744+
if (!fw_dump.param_area || sysfs_create_file(fadump_kobj, &bootargs_append_attr.attr)) {
1745+
pr_warn("WARNING: Could not setup area to pass additional parameters!\n");
1746+
return;
1747+
}
1748+
1749+
memset(phys_to_virt(fw_dump.param_area), 0, COMMAND_LINE_SIZE);
1750+
}
1751+
16661752
/*
16671753
* Prepare for firmware-assisted dump.
16681754
*/
@@ -1686,6 +1772,7 @@ int __init setup_fadump(void)
16861772
}
16871773
/* Initialize the kernel dump memory structure and register with f/w */
16881774
else if (fw_dump.reserve_dump_area_size) {
1775+
fadump_setup_param_area();
16891776
fw_dump.ops->fadump_init_mem_struct(&fw_dump);
16901777
register_fadump();
16911778
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,10 @@ void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
665665
}
666666
}
667667

668-
fadump_conf->ops = &opal_fadump_ops;
669-
fadump_conf->fadump_supported = 1;
668+
fadump_conf->ops = &opal_fadump_ops;
669+
fadump_conf->fadump_supported = 1;
670+
/* TODO: Add support to pass additional parameters */
671+
fadump_conf->param_area_supported = 0;
670672

671673
/*
672674
* 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 __init 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;
@@ -453,6 +467,13 @@ static int __init rtas_fadump_process(struct fw_dump *fadump_conf)
453467
return rc;
454468
}
455469
break;
470+
case RTAS_FADUMP_PARAM_AREA:
471+
if (fdm_active->rgn[i].bytes_dumped != fdm_active->rgn[i].source_len ||
472+
fdm_active->rgn[i].error_flags != 0) {
473+
pr_warn("Failed to process additional parameters! Proceeding anyway..\n");
474+
fadump_conf->param_area = 0;
475+
}
476+
break;
456477
default:
457478
/*
458479
* If the first/crashed kernel added a new region type that the
@@ -509,6 +530,13 @@ static void rtas_fadump_region_show(struct fw_dump *fadump_conf,
509530
be64_to_cpu(fdm_ptr->rgn[i].source_len),
510531
be64_to_cpu(fdm_ptr->rgn[i].bytes_dumped));
511532
break;
533+
case RTAS_FADUMP_PARAM_AREA:
534+
seq_printf(m, "\n[%#016llx-%#016llx]: cmdline append: '%s'\n",
535+
be64_to_cpu(fdm_ptr->rgn[i].destination_address),
536+
be64_to_cpu(fdm_ptr->rgn[i].destination_address) +
537+
be64_to_cpu(fdm_ptr->rgn[i].source_len) - 1,
538+
(char *)__va(be64_to_cpu(fdm_ptr->rgn[i].destination_address)));
539+
break;
512540
default:
513541
seq_printf(m, "Unknown region type %d : Src: %#016llx, Dest: %#016llx, ",
514542
type, be64_to_cpu(fdm_ptr->rgn[i].source_address),
@@ -571,9 +599,10 @@ void __init rtas_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
571599
if (!token)
572600
return;
573601

574-
fadump_conf->ibm_configure_kernel_dump = be32_to_cpu(*token);
575-
fadump_conf->ops = &rtas_fadump_ops;
576-
fadump_conf->fadump_supported = 1;
602+
fadump_conf->ibm_configure_kernel_dump = be32_to_cpu(*token);
603+
fadump_conf->ops = &rtas_fadump_ops;
604+
fadump_conf->fadump_supported = 1;
605+
fadump_conf->param_area_supported = 1;
577606

578607
/* Firmware supports 64-bit value for size, align it to pagesize. */
579608
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)