Skip to content

Commit 5b365e7

Browse files
committed
Merge: Updates for fadump multiple boot memory regions
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/5646 Description: Updates for fadump multiple boot memory regions JIRA: https://issues.redhat.com/browse/RHEL-52914 Build Info: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=65479275 Tested: Verified Brew build test kernel RPMs Signed-off-by: Mamatha Inamdar <minamdar@redhat.com> Approved-by: Steve Best <sbest@redhat.com> Approved-by: Tony Camuso <tcamuso@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Rado Vrbovsky <rvrbovsk@redhat.com>
2 parents 5e02fed + 44b6827 commit 5b365e7

File tree

8 files changed

+375
-126
lines changed

8 files changed

+375
-126
lines changed

Documentation/ABI/testing/sysfs-kernel-fadump

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,10 @@ Contact: linuxppc-dev@lists.ozlabs.org
3838
Description: read only
3939
Provide information about the amount of memory reserved by
4040
FADump to save the crash dump in bytes.
41+
42+
What: /sys/kernel/fadump/bootargs_append
43+
Date: May 2024
44+
Contact: linuxppc-dev@lists.ozlabs.org
45+
Description: read/write
46+
This is a special sysfs file available to setup additional
47+
parameters to be passed to capture kernel.

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

Lines changed: 4 additions & 1 deletion
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
};
@@ -129,14 +132,14 @@ struct fadump_ops {
129132
struct seq_file *m);
130133
void (*fadump_trigger)(struct fadump_crash_info_header *fdh,
131134
const char *msg);
135+
int (*fadump_max_boot_mem_rgns)(void);
132136
};
133137

134138
/* Helper functions */
135139
s32 __init fadump_setup_cpu_notes_buf(u32 num_cpus);
136140
void fadump_free_cpu_notes_buf(void);
137141
u32 *__init fadump_regs_to_elf_notes(u32 *buf, struct pt_regs *regs);
138142
void __init fadump_update_elfcore_header(char *bufp);
139-
bool is_fadump_boot_mem_contiguous(void);
140143
bool is_fadump_reserved_mem_contiguous(void);
141144

142145
#else /* !CONFIG_PRESERVE_FA_DUMP */

arch/powerpc/include/asm/fadump.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ extern int is_fadump_active(void);
1919
extern int should_fadump_crash(void);
2020
extern void crash_fadump(struct pt_regs *, const char *);
2121
extern void fadump_cleanup(void);
22+
extern void fadump_append_bootargs(void);
2223

2324
#else /* CONFIG_FA_DUMP */
2425
static inline int is_fadump_active(void) { return 0; }
2526
static inline int should_fadump_crash(void) { return 0; }
2627
static inline void crash_fadump(struct pt_regs *regs, const char *str) { }
2728
static inline void fadump_cleanup(void) { }
29+
static inline void fadump_append_bootargs(void) { }
2830
#endif /* !CONFIG_FA_DUMP */
2931

3032
#if defined(CONFIG_FA_DUMP) || defined(CONFIG_PRESERVE_FA_DUMP)

arch/powerpc/kernel/fadump.c

Lines changed: 127 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,41 @@ static int __init fadump_cma_init(void)
133133
static int __init fadump_cma_init(void) { return 1; }
134134
#endif /* CONFIG_CMA */
135135

136+
/*
137+
* Additional parameters meant for capture kernel are placed in a dedicated area.
138+
* If this is capture kernel boot, append these parameters to bootargs.
139+
*/
140+
void __init fadump_append_bootargs(void)
141+
{
142+
char *append_args;
143+
size_t len;
144+
145+
if (!fw_dump.dump_active || !fw_dump.param_area_supported || !fw_dump.param_area)
146+
return;
147+
148+
if (fw_dump.param_area >= fw_dump.boot_mem_top) {
149+
if (memblock_reserve(fw_dump.param_area, COMMAND_LINE_SIZE)) {
150+
pr_warn("WARNING: Can't use additional parameters area!\n");
151+
fw_dump.param_area = 0;
152+
return;
153+
}
154+
}
155+
156+
append_args = (char *)fw_dump.param_area;
157+
len = strlen(boot_command_line);
158+
159+
/*
160+
* Too late to fail even if cmdline size exceeds. Truncate additional parameters
161+
* to cmdline size and proceed anyway.
162+
*/
163+
if (len + strlen(append_args) >= COMMAND_LINE_SIZE - 1)
164+
pr_warn("WARNING: Appending parameters exceeds cmdline size. Truncating!\n");
165+
166+
pr_debug("Cmdline: %s\n", boot_command_line);
167+
snprintf(boot_command_line + len, COMMAND_LINE_SIZE - len, " %s", append_args);
168+
pr_info("Updated cmdline: %s\n", boot_command_line);
169+
}
170+
136171
/* Scan the Firmware Assisted dump configuration details. */
137172
int __init early_init_dt_scan_fw_dump(unsigned long node, const char *uname,
138173
int depth, void *data)
@@ -222,28 +257,6 @@ static bool is_fadump_mem_area_contiguous(u64 d_start, u64 d_end)
222257
return ret;
223258
}
224259

225-
/*
226-
* Returns true, if there are no holes in boot memory area,
227-
* false otherwise.
228-
*/
229-
bool is_fadump_boot_mem_contiguous(void)
230-
{
231-
unsigned long d_start, d_end;
232-
bool ret = false;
233-
int i;
234-
235-
for (i = 0; i < fw_dump.boot_mem_regs_cnt; i++) {
236-
d_start = fw_dump.boot_mem_addr[i];
237-
d_end = d_start + fw_dump.boot_mem_sz[i];
238-
239-
ret = is_fadump_mem_area_contiguous(d_start, d_end);
240-
if (!ret)
241-
break;
242-
}
243-
244-
return ret;
245-
}
246-
247260
/*
248261
* Returns true, if there are no holes in reserved memory area,
249262
* false otherwise.
@@ -389,10 +402,11 @@ static unsigned long __init get_fadump_area_size(void)
389402
static int __init add_boot_mem_region(unsigned long rstart,
390403
unsigned long rsize)
391404
{
405+
int max_boot_mem_rgns = fw_dump.ops->fadump_max_boot_mem_rgns();
392406
int i = fw_dump.boot_mem_regs_cnt++;
393407

394-
if (fw_dump.boot_mem_regs_cnt > FADUMP_MAX_MEM_REGS) {
395-
fw_dump.boot_mem_regs_cnt = FADUMP_MAX_MEM_REGS;
408+
if (fw_dump.boot_mem_regs_cnt > max_boot_mem_rgns) {
409+
fw_dump.boot_mem_regs_cnt = max_boot_mem_rgns;
396410
return 0;
397411
}
398412

@@ -1498,6 +1512,43 @@ static ssize_t registered_show(struct kobject *kobj,
14981512
return sprintf(buf, "%d\n", fw_dump.dump_registered);
14991513
}
15001514

1515+
static ssize_t bootargs_append_show(struct kobject *kobj,
1516+
struct kobj_attribute *attr,
1517+
char *buf)
1518+
{
1519+
return sprintf(buf, "%s\n", (char *)__va(fw_dump.param_area));
1520+
}
1521+
1522+
static ssize_t bootargs_append_store(struct kobject *kobj,
1523+
struct kobj_attribute *attr,
1524+
const char *buf, size_t count)
1525+
{
1526+
char *params;
1527+
1528+
if (!fw_dump.fadump_enabled || fw_dump.dump_active)
1529+
return -EPERM;
1530+
1531+
if (count >= COMMAND_LINE_SIZE)
1532+
return -EINVAL;
1533+
1534+
/*
1535+
* Fail here instead of handling this scenario with
1536+
* some silly workaround in capture kernel.
1537+
*/
1538+
if (strlen(saved_command_line) + count >= COMMAND_LINE_SIZE) {
1539+
pr_err("Appending parameters exceeds cmdline size!\n");
1540+
return -ENOSPC;
1541+
}
1542+
1543+
params = __va(fw_dump.param_area);
1544+
strscpy_pad(params, buf, COMMAND_LINE_SIZE);
1545+
/* Remove newline character at the end. */
1546+
if (params[count-1] == '\n')
1547+
params[count-1] = '\0';
1548+
1549+
return count;
1550+
}
1551+
15011552
static ssize_t registered_store(struct kobject *kobj,
15021553
struct kobj_attribute *attr,
15031554
const char *buf, size_t count)
@@ -1556,6 +1607,7 @@ static struct kobj_attribute release_attr = __ATTR_WO(release_mem);
15561607
static struct kobj_attribute enable_attr = __ATTR_RO(enabled);
15571608
static struct kobj_attribute register_attr = __ATTR_RW(registered);
15581609
static struct kobj_attribute mem_reserved_attr = __ATTR_RO(mem_reserved);
1610+
static struct kobj_attribute bootargs_append_attr = __ATTR_RW(bootargs_append);
15591611

15601612
static struct attribute *fadump_attrs[] = {
15611613
&enable_attr.attr,
@@ -1632,6 +1684,54 @@ static void __init fadump_init_files(void)
16321684
return;
16331685
}
16341686

1687+
/*
1688+
* Reserve memory to store additional parameters to be passed
1689+
* for fadump/capture kernel.
1690+
*/
1691+
static void __init fadump_setup_param_area(void)
1692+
{
1693+
phys_addr_t range_start, range_end;
1694+
1695+
if (!fw_dump.param_area_supported || fw_dump.dump_active)
1696+
return;
1697+
1698+
/* This memory can't be used by PFW or bootloader as it is shared across kernels */
1699+
if (radix_enabled()) {
1700+
/*
1701+
* Anywhere in the upper half should be good enough as all memory
1702+
* is accessible in real mode.
1703+
*/
1704+
range_start = memblock_end_of_DRAM() / 2;
1705+
range_end = memblock_end_of_DRAM();
1706+
} else {
1707+
/*
1708+
* Passing additional parameters is supported for hash MMU only
1709+
* if the first memory block size is 768MB or higher.
1710+
*/
1711+
if (ppc64_rma_size < 0x30000000)
1712+
return;
1713+
1714+
/*
1715+
* 640 MB to 768 MB is not used by PFW/bootloader. So, try reserving
1716+
* memory for passing additional parameters in this range to avoid
1717+
* being stomped on by PFW/bootloader.
1718+
*/
1719+
range_start = 0x2A000000;
1720+
range_end = range_start + 0x4000000;
1721+
}
1722+
1723+
fw_dump.param_area = memblock_phys_alloc_range(COMMAND_LINE_SIZE,
1724+
COMMAND_LINE_SIZE,
1725+
range_start,
1726+
range_end);
1727+
if (!fw_dump.param_area || sysfs_create_file(fadump_kobj, &bootargs_append_attr.attr)) {
1728+
pr_warn("WARNING: Could not setup area to pass additional parameters!\n");
1729+
return;
1730+
}
1731+
1732+
memset(phys_to_virt(fw_dump.param_area), 0, COMMAND_LINE_SIZE);
1733+
}
1734+
16351735
/*
16361736
* Prepare for firmware-assisted dump.
16371737
*/
@@ -1659,8 +1759,10 @@ int __init setup_fadump(void)
16591759
fadump_invalidate_release_mem();
16601760
}
16611761
/* Initialize the kernel dump memory structure for FAD registration. */
1662-
else if (fw_dump.reserve_dump_area_size)
1762+
else if (fw_dump.reserve_dump_area_size) {
1763+
fadump_setup_param_area();
16631764
fw_dump.ops->fadump_init_mem_struct(&fw_dump);
1765+
}
16641766

16651767
/*
16661768
* In case of panic, fadump is triggered via ppc_panic_event()

arch/powerpc/kernel/prom.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,9 @@ void __init early_init_devtree(void *params)
786786
*/
787787
of_scan_flat_dt(early_init_dt_scan_chosen_ppc, boot_command_line);
788788

789+
/* Append additional parameters passed for fadump capture kernel */
790+
fadump_append_bootargs();
791+
789792
/* Scan memory nodes and rebuild MEMBLOCKs */
790793
early_init_dt_scan_root();
791794
early_init_dt_scan_memory_ppc();

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,12 @@ static void opal_fadump_trigger(struct fadump_crash_info_header *fdh,
606606
pr_emerg("No backend support for MPIPL!\n");
607607
}
608608

609+
/* FADUMP_MAX_MEM_REGS or lower */
610+
static int opal_fadump_max_boot_mem_rgns(void)
611+
{
612+
return FADUMP_MAX_MEM_REGS;
613+
}
614+
609615
static struct fadump_ops opal_fadump_ops = {
610616
.fadump_init_mem_struct = opal_fadump_init_mem_struct,
611617
.fadump_get_metadata_size = opal_fadump_get_metadata_size,
@@ -618,6 +624,7 @@ static struct fadump_ops opal_fadump_ops = {
618624
.fadump_process = opal_fadump_process,
619625
.fadump_region_show = opal_fadump_region_show,
620626
.fadump_trigger = opal_fadump_trigger,
627+
.fadump_max_boot_mem_rgns = opal_fadump_max_boot_mem_rgns,
621628
};
622629

623630
void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
@@ -664,8 +671,10 @@ void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
664671
}
665672
}
666673

667-
fadump_conf->ops = &opal_fadump_ops;
668-
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;
669678

670679
/*
671680
* Firmware supports 32-bit field for size. Align it to PAGE_SIZE

0 commit comments

Comments
 (0)