Skip to content

Commit

Permalink
Automatic merge of 'next-test' into merge-test (2024-05-10 17:46)
Browse files Browse the repository at this point in the history
  • Loading branch information
mpe committed May 10, 2024
2 parents 0a3850f + 3416c9d commit 0a217c8
Show file tree
Hide file tree
Showing 7 changed files with 366 additions and 125 deletions.
5 changes: 4 additions & 1 deletion arch/powerpc/include/asm/fadump-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ struct fw_dump {
unsigned long cpu_notes_buf_vaddr;
unsigned long cpu_notes_buf_size;

unsigned long param_area;

/*
* Maximum size supported by firmware to copy from source to
* destination address per entry.
Expand All @@ -138,6 +140,7 @@ struct fw_dump {
unsigned long dump_active:1;
unsigned long dump_registered:1;
unsigned long nocma:1;
unsigned long param_area_supported:1;

struct fadump_ops *ops;
};
Expand All @@ -156,14 +159,14 @@ struct fadump_ops {
struct seq_file *m);
void (*fadump_trigger)(struct fadump_crash_info_header *fdh,
const char *msg);
int (*fadump_max_boot_mem_rgns)(void);
};

/* Helper functions */
s32 __init fadump_setup_cpu_notes_buf(u32 num_cpus);
void fadump_free_cpu_notes_buf(void);
u32 *__init fadump_regs_to_elf_notes(u32 *buf, struct pt_regs *regs);
void __init fadump_update_elfcore_header(char *bufp);
bool is_fadump_boot_mem_contiguous(void);
bool is_fadump_reserved_mem_contiguous(void);

#else /* !CONFIG_PRESERVE_FA_DUMP */
Expand Down
2 changes: 2 additions & 0 deletions arch/powerpc/include/asm/fadump.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ extern int is_fadump_active(void);
extern int should_fadump_crash(void);
extern void crash_fadump(struct pt_regs *, const char *);
extern void fadump_cleanup(void);
extern void fadump_append_bootargs(void);

#else /* CONFIG_FA_DUMP */
static inline int is_fadump_active(void) { return 0; }
static inline int should_fadump_crash(void) { return 0; }
static inline void crash_fadump(struct pt_regs *regs, const char *str) { }
static inline void fadump_cleanup(void) { }
static inline void fadump_append_bootargs(void) { }
#endif /* !CONFIG_FA_DUMP */

#if defined(CONFIG_FA_DUMP) || defined(CONFIG_PRESERVE_FA_DUMP)
Expand Down
149 changes: 125 additions & 24 deletions arch/powerpc/kernel/fadump.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,41 @@ static int __init fadump_cma_init(void)
static int __init fadump_cma_init(void) { return 1; }
#endif /* CONFIG_CMA */

/*
* Additional parameters meant for capture kernel are placed in a dedicated area.
* If this is capture kernel boot, append these parameters to bootargs.
*/
void __init fadump_append_bootargs(void)
{
char *append_args;
size_t len;

if (!fw_dump.dump_active || !fw_dump.param_area_supported || !fw_dump.param_area)
return;

if (fw_dump.param_area >= fw_dump.boot_mem_top) {
if (memblock_reserve(fw_dump.param_area, COMMAND_LINE_SIZE)) {
pr_warn("WARNING: Can't use additional parameters area!\n");
fw_dump.param_area = 0;
return;
}
}

append_args = (char *)fw_dump.param_area;
len = strlen(boot_command_line);

/*
* Too late to fail even if cmdline size exceeds. Truncate additional parameters
* to cmdline size and proceed anyway.
*/
if (len + strlen(append_args) >= COMMAND_LINE_SIZE - 1)
pr_warn("WARNING: Appending parameters exceeds cmdline size. Truncating!\n");

pr_debug("Cmdline: %s\n", boot_command_line);
snprintf(boot_command_line + len, COMMAND_LINE_SIZE - len, " %s", append_args);
pr_info("Updated cmdline: %s\n", boot_command_line);
}

/* Scan the Firmware Assisted dump configuration details. */
int __init early_init_dt_scan_fw_dump(unsigned long node, const char *uname,
int depth, void *data)
Expand Down Expand Up @@ -220,28 +255,6 @@ static bool is_fadump_mem_area_contiguous(u64 d_start, u64 d_end)
return ret;
}

/*
* Returns true, if there are no holes in boot memory area,
* false otherwise.
*/
bool is_fadump_boot_mem_contiguous(void)
{
unsigned long d_start, d_end;
bool ret = false;
int i;

for (i = 0; i < fw_dump.boot_mem_regs_cnt; i++) {
d_start = fw_dump.boot_mem_addr[i];
d_end = d_start + fw_dump.boot_mem_sz[i];

ret = is_fadump_mem_area_contiguous(d_start, d_end);
if (!ret)
break;
}

return ret;
}

/*
* Returns true, if there are no holes in reserved memory area,
* false otherwise.
Expand Down Expand Up @@ -381,10 +394,11 @@ static unsigned long __init get_fadump_area_size(void)
static int __init add_boot_mem_region(unsigned long rstart,
unsigned long rsize)
{
int max_boot_mem_rgns = fw_dump.ops->fadump_max_boot_mem_rgns();
int i = fw_dump.boot_mem_regs_cnt++;

if (fw_dump.boot_mem_regs_cnt > FADUMP_MAX_MEM_REGS) {
fw_dump.boot_mem_regs_cnt = FADUMP_MAX_MEM_REGS;
if (fw_dump.boot_mem_regs_cnt > max_boot_mem_rgns) {
fw_dump.boot_mem_regs_cnt = max_boot_mem_rgns;
return 0;
}

Expand Down Expand Up @@ -1452,6 +1466,43 @@ static ssize_t registered_show(struct kobject *kobj,
return sprintf(buf, "%d\n", fw_dump.dump_registered);
}

static ssize_t bootargs_append_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
return sprintf(buf, "%s\n", (char *)__va(fw_dump.param_area));
}

static ssize_t bootargs_append_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
char *params;

if (!fw_dump.fadump_enabled || fw_dump.dump_active)
return -EPERM;

if (count >= COMMAND_LINE_SIZE)
return -EINVAL;

/*
* Fail here instead of handling this scenario with
* some silly workaround in capture kernel.
*/
if (saved_command_line_len + count >= COMMAND_LINE_SIZE) {
pr_err("Appending parameters exceeds cmdline size!\n");
return -ENOSPC;
}

params = __va(fw_dump.param_area);
strscpy_pad(params, buf, COMMAND_LINE_SIZE);
/* Remove newline character at the end. */
if (params[count-1] == '\n')
params[count-1] = '\0';

return count;
}

static ssize_t registered_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
Expand Down Expand Up @@ -1511,6 +1562,7 @@ static struct kobj_attribute enable_attr = __ATTR_RO(enabled);
static struct kobj_attribute register_attr = __ATTR_RW(registered);
static struct kobj_attribute mem_reserved_attr = __ATTR_RO(mem_reserved);
static struct kobj_attribute hotplug_ready_attr = __ATTR_RO(hotplug_ready);
static struct kobj_attribute bootargs_append_attr = __ATTR_RW(bootargs_append);

static struct attribute *fadump_attrs[] = {
&enable_attr.attr,
Expand Down Expand Up @@ -1684,6 +1736,54 @@ static void __init fadump_process(void)
fadump_invalidate_release_mem();
}

/*
* Reserve memory to store additional parameters to be passed
* for fadump/capture kernel.
*/
static void fadump_setup_param_area(void)
{
phys_addr_t range_start, range_end;

if (!fw_dump.param_area_supported || fw_dump.dump_active)
return;

/* This memory can't be used by PFW or bootloader as it is shared across kernels */
if (radix_enabled()) {
/*
* Anywhere in the upper half should be good enough as all memory
* is accessible in real mode.
*/
range_start = memblock_end_of_DRAM() / 2;
range_end = memblock_end_of_DRAM();
} else {
/*
* Passing additional parameters is supported for hash MMU only
* if the first memory block size is 768MB or higher.
*/
if (ppc64_rma_size < 0x30000000)
return;

/*
* 640 MB to 768 MB is not used by PFW/bootloader. So, try reserving
* memory for passing additional parameters in this range to avoid
* being stomped on by PFW/bootloader.
*/
range_start = 0x2A000000;
range_end = range_start + 0x4000000;
}

fw_dump.param_area = memblock_phys_alloc_range(COMMAND_LINE_SIZE,
COMMAND_LINE_SIZE,
range_start,
range_end);
if (!fw_dump.param_area || sysfs_create_file(fadump_kobj, &bootargs_append_attr.attr)) {
pr_warn("WARNING: Could not setup area to pass additional parameters!\n");
return;
}

memset(phys_to_virt(fw_dump.param_area), 0, COMMAND_LINE_SIZE);
}

/*
* Prepare for firmware-assisted dump.
*/
Expand All @@ -1707,6 +1807,7 @@ int __init setup_fadump(void)
}
/* Initialize the kernel dump memory structure and register with f/w */
else if (fw_dump.reserve_dump_area_size) {
fadump_setup_param_area();
fw_dump.ops->fadump_init_mem_struct(&fw_dump);
register_fadump();
}
Expand Down
3 changes: 3 additions & 0 deletions arch/powerpc/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,9 @@ void __init early_init_devtree(void *params)
*/
of_scan_flat_dt(early_init_dt_scan_chosen_ppc, boot_command_line);

/* Append additional parameters passed for fadump capture kernel */
fadump_append_bootargs();

/* Scan memory nodes and rebuild MEMBLOCKs */
early_init_dt_scan_root();
early_init_dt_scan_memory_ppc();
Expand Down
13 changes: 11 additions & 2 deletions arch/powerpc/platforms/powernv/opal-fadump.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,12 @@ static void opal_fadump_trigger(struct fadump_crash_info_header *fdh,
pr_emerg("No backend support for MPIPL!\n");
}

/* FADUMP_MAX_MEM_REGS or lower */
static int opal_fadump_max_boot_mem_rgns(void)
{
return FADUMP_MAX_MEM_REGS;
}

static struct fadump_ops opal_fadump_ops = {
.fadump_init_mem_struct = opal_fadump_init_mem_struct,
.fadump_get_metadata_size = opal_fadump_get_metadata_size,
Expand All @@ -611,6 +617,7 @@ static struct fadump_ops opal_fadump_ops = {
.fadump_process = opal_fadump_process,
.fadump_region_show = opal_fadump_region_show,
.fadump_trigger = opal_fadump_trigger,
.fadump_max_boot_mem_rgns = opal_fadump_max_boot_mem_rgns,
};

void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
Expand Down Expand Up @@ -658,8 +665,10 @@ void __init opal_fadump_dt_scan(struct fw_dump *fadump_conf, u64 node)
}
}

fadump_conf->ops = &opal_fadump_ops;
fadump_conf->fadump_supported = 1;
fadump_conf->ops = &opal_fadump_ops;
fadump_conf->fadump_supported = 1;
/* TODO: Add support to pass additional parameters */
fadump_conf->param_area_supported = 0;

/*
* Firmware supports 32-bit field for size. Align it to PAGE_SIZE
Expand Down
Loading

0 comments on commit 0a217c8

Please sign in to comment.