Commit 41a65d16 authored by Hari Bathini's avatar Hari Bathini Committed by Michael Ellerman

pseries/fadump: define RTAS register/un-register callback functions

Move platform specific register/un-register code, the RTAS calls, to
register/un-register callback functions. This would also mean moving
code that initializes and prints the platform specific FADump data.
Signed-off-by: default avatarHari Bathini <hbathini@linux.ibm.com>
Reviewed-by: default avatarMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/156821332856.5656.16380417702046411631.stgit@hbathini.in.ibm.com
parent d3833a70
...@@ -89,7 +89,9 @@ struct fw_dump { ...@@ -89,7 +89,9 @@ struct fw_dump {
unsigned long cpu_state_data_size; unsigned long cpu_state_data_size;
unsigned long hpte_region_size; unsigned long hpte_region_size;
unsigned long boot_memory_size; unsigned long boot_memory_size;
u64 boot_mem_dest_addr;
unsigned long fadumphdr_addr; unsigned long fadumphdr_addr;
unsigned long cpu_notes_buf_vaddr; unsigned long cpu_notes_buf_vaddr;
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include "../platforms/pseries/rtas-fadump.h" #include "../platforms/pseries/rtas-fadump.h"
static struct fw_dump fw_dump; static struct fw_dump fw_dump;
static struct rtas_fadump_mem_struct fdm;
static const struct rtas_fadump_mem_struct *fdm_active; static const struct rtas_fadump_mem_struct *fdm_active;
static DEFINE_MUTEX(fadump_mutex); static DEFINE_MUTEX(fadump_mutex);
...@@ -229,61 +228,6 @@ static void fadump_show_config(void) ...@@ -229,61 +228,6 @@ static void fadump_show_config(void)
pr_debug("Boot memory size : %lx\n", fw_dump.boot_memory_size); pr_debug("Boot memory size : %lx\n", fw_dump.boot_memory_size);
} }
static unsigned long init_fadump_mem_struct(struct rtas_fadump_mem_struct *fdm,
unsigned long addr)
{
if (!fdm)
return 0;
memset(fdm, 0, sizeof(struct rtas_fadump_mem_struct));
addr = addr & PAGE_MASK;
fdm->header.dump_format_version = cpu_to_be32(0x00000001);
fdm->header.dump_num_sections = cpu_to_be16(3);
fdm->header.dump_status_flag = 0;
fdm->header.offset_first_dump_section =
cpu_to_be32((u32)offsetof(struct rtas_fadump_mem_struct, cpu_state_data));
/*
* Fields for disk dump option.
* We are not using disk dump option, hence set these fields to 0.
*/
fdm->header.dd_block_size = 0;
fdm->header.dd_block_offset = 0;
fdm->header.dd_num_blocks = 0;
fdm->header.dd_offset_disk_path = 0;
/* set 0 to disable an automatic dump-reboot. */
fdm->header.max_time_auto = 0;
/* Kernel dump sections */
/* cpu state data section. */
fdm->cpu_state_data.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
fdm->cpu_state_data.source_data_type = cpu_to_be16(RTAS_FADUMP_CPU_STATE_DATA);
fdm->cpu_state_data.source_address = 0;
fdm->cpu_state_data.source_len = cpu_to_be64(fw_dump.cpu_state_data_size);
fdm->cpu_state_data.destination_address = cpu_to_be64(addr);
addr += fw_dump.cpu_state_data_size;
/* hpte region section */
fdm->hpte_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
fdm->hpte_region.source_data_type = cpu_to_be16(RTAS_FADUMP_HPTE_REGION);
fdm->hpte_region.source_address = 0;
fdm->hpte_region.source_len = cpu_to_be64(fw_dump.hpte_region_size);
fdm->hpte_region.destination_address = cpu_to_be64(addr);
addr += fw_dump.hpte_region_size;
/* RMA region section */
fdm->rmr_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
fdm->rmr_region.source_data_type = cpu_to_be16(RTAS_FADUMP_REAL_MODE_REGION);
fdm->rmr_region.source_address = cpu_to_be64(RMA_START);
fdm->rmr_region.source_len = cpu_to_be64(fw_dump.boot_memory_size);
fdm->rmr_region.destination_address = cpu_to_be64(addr);
addr += fw_dump.boot_memory_size;
return addr;
}
/** /**
* fadump_calculate_reserve_size(): reserve variable boot area 5% of System RAM * fadump_calculate_reserve_size(): reserve variable boot area 5% of System RAM
* *
...@@ -546,61 +490,6 @@ static int __init early_fadump_reserve_mem(char *p) ...@@ -546,61 +490,6 @@ static int __init early_fadump_reserve_mem(char *p)
} }
early_param("fadump_reserve_mem", early_fadump_reserve_mem); early_param("fadump_reserve_mem", early_fadump_reserve_mem);
static int register_fw_dump(struct rtas_fadump_mem_struct *fdm)
{
int rc, err;
unsigned int wait_time;
pr_debug("Registering for firmware-assisted kernel dump...\n");
/* TODO: Add upper time limit for the delay */
do {
rc = rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1, NULL,
FADUMP_REGISTER, fdm,
sizeof(struct rtas_fadump_mem_struct));
wait_time = rtas_busy_delay_time(rc);
if (wait_time)
mdelay(wait_time);
} while (wait_time);
err = -EIO;
switch (rc) {
default:
pr_err("Failed to register. Unknown Error(%d).\n", rc);
break;
case -1:
printk(KERN_ERR "Failed to register firmware-assisted kernel"
" dump. Hardware Error(%d).\n", rc);
break;
case -3:
if (!is_fadump_boot_mem_contiguous())
pr_err("Can't have holes in boot memory area while registering fadump\n");
else if (!is_fadump_reserved_mem_contiguous())
pr_err("Can't have holes in reserved memory area while"
" registering fadump\n");
printk(KERN_ERR "Failed to register firmware-assisted kernel"
" dump. Parameter Error(%d).\n", rc);
err = -EINVAL;
break;
case -9:
printk(KERN_ERR "firmware-assisted kernel dump is already "
" registered.");
fw_dump.dump_registered = 1;
err = -EEXIST;
break;
case 0:
printk(KERN_INFO "firmware-assisted kernel dump registration"
" is successful\n");
fw_dump.dump_registered = 1;
err = 0;
break;
}
return err;
}
void crash_fadump(struct pt_regs *regs, const char *str) void crash_fadump(struct pt_regs *regs, const char *str)
{ {
struct fadump_crash_info_header *fdh = NULL; struct fadump_crash_info_header *fdh = NULL;
...@@ -643,8 +532,7 @@ void crash_fadump(struct pt_regs *regs, const char *str) ...@@ -643,8 +532,7 @@ void crash_fadump(struct pt_regs *regs, const char *str)
fdh->online_mask = *cpu_online_mask; fdh->online_mask = *cpu_online_mask;
/* Call ibm,os-term rtas call to trigger firmware assisted dump */ fw_dump.ops->fadump_trigger(fdh, str);
rtas_os_term((char *)str);
} }
#define GPR_MASK 0xffffff0000000000 #define GPR_MASK 0xffffff0000000000
...@@ -1129,7 +1017,7 @@ static int fadump_setup_crash_memory_ranges(void) ...@@ -1129,7 +1017,7 @@ static int fadump_setup_crash_memory_ranges(void)
static inline unsigned long fadump_relocate(unsigned long paddr) static inline unsigned long fadump_relocate(unsigned long paddr)
{ {
if (paddr > RMA_START && paddr < fw_dump.boot_memory_size) if (paddr > RMA_START && paddr < fw_dump.boot_memory_size)
return be64_to_cpu(fdm.rmr_region.destination_address) + paddr; return fw_dump.boot_mem_dest_addr + paddr;
else else
return paddr; return paddr;
} }
...@@ -1202,7 +1090,7 @@ static int fadump_create_elfcore_headers(char *bufp) ...@@ -1202,7 +1090,7 @@ static int fadump_create_elfcore_headers(char *bufp)
* to the specified destination_address. Hence set * to the specified destination_address. Hence set
* the correct offset. * the correct offset.
*/ */
phdr->p_offset = be64_to_cpu(fdm.rmr_region.destination_address); phdr->p_offset = fw_dump.boot_mem_dest_addr;
} }
phdr->p_paddr = mbase; phdr->p_paddr = mbase;
...@@ -1254,7 +1142,8 @@ static int register_fadump(void) ...@@ -1254,7 +1142,8 @@ static int register_fadump(void)
if (ret) if (ret)
return ret; return ret;
addr = be64_to_cpu(fdm.rmr_region.destination_address) + be64_to_cpu(fdm.rmr_region.source_len); addr = fw_dump.fadumphdr_addr;
/* Initialize fadump crash info header. */ /* Initialize fadump crash info header. */
addr = init_fadump_header(addr); addr = init_fadump_header(addr);
vaddr = __va(addr); vaddr = __va(addr);
...@@ -1263,34 +1152,8 @@ static int register_fadump(void) ...@@ -1263,34 +1152,8 @@ static int register_fadump(void)
fadump_create_elfcore_headers(vaddr); fadump_create_elfcore_headers(vaddr);
/* register the future kernel dump with firmware. */ /* register the future kernel dump with firmware. */
return register_fw_dump(&fdm); pr_debug("Registering for firmware-assisted kernel dump...\n");
} return fw_dump.ops->fadump_register(&fw_dump);
static int fadump_unregister_dump(struct rtas_fadump_mem_struct *fdm)
{
int rc = 0;
unsigned int wait_time;
pr_debug("Un-register firmware-assisted dump\n");
/* TODO: Add upper time limit for the delay */
do {
rc = rtas_call(fw_dump.ibm_configure_kernel_dump, 3, 1, NULL,
FADUMP_UNREGISTER, fdm,
sizeof(struct rtas_fadump_mem_struct));
wait_time = rtas_busy_delay_time(rc);
if (wait_time)
mdelay(wait_time);
} while (wait_time);
if (rc) {
printk(KERN_ERR "Failed to un-register firmware-assisted dump."
" unexpected error(%d).\n", rc);
return rc;
}
fw_dump.dump_registered = 0;
return 0;
} }
static int fadump_invalidate_dump(const struct rtas_fadump_mem_struct *fdm) static int fadump_invalidate_dump(const struct rtas_fadump_mem_struct *fdm)
...@@ -1328,7 +1191,7 @@ void fadump_cleanup(void) ...@@ -1328,7 +1191,7 @@ void fadump_cleanup(void)
fadump_invalidate_dump(fdm_active); fadump_invalidate_dump(fdm_active);
} else if (fw_dump.dump_registered) { } else if (fw_dump.dump_registered) {
/* Un-register Firmware-assisted dump if it was registered. */ /* Un-register Firmware-assisted dump if it was registered. */
fadump_unregister_dump(&fdm); fw_dump.ops->fadump_unregister(&fw_dump);
free_crash_memory_ranges(); free_crash_memory_ranges();
} }
} }
...@@ -1433,7 +1296,7 @@ static void fadump_invalidate_release_mem(void) ...@@ -1433,7 +1296,7 @@ static void fadump_invalidate_release_mem(void)
fadump_free_cpu_notes_buf(); fadump_free_cpu_notes_buf();
/* Initialize the kernel dump memory structure for FAD registration. */ /* Initialize the kernel dump memory structure for FAD registration. */
init_fadump_mem_struct(&fdm, fw_dump.reserve_dump_area_start); fw_dump.ops->fadump_init_mem_struct(&fw_dump);
} }
static ssize_t fadump_release_memory_store(struct kobject *kobj, static ssize_t fadump_release_memory_store(struct kobject *kobj,
...@@ -1498,12 +1361,13 @@ static ssize_t fadump_register_store(struct kobject *kobj, ...@@ -1498,12 +1361,13 @@ static ssize_t fadump_register_store(struct kobject *kobj,
goto unlock_out; goto unlock_out;
} }
/* Un-register Firmware-assisted dump */ /* Un-register Firmware-assisted dump */
fadump_unregister_dump(&fdm); pr_debug("Un-register firmware-assisted dump\n");
fw_dump.ops->fadump_unregister(&fw_dump);
break; break;
case 1: case 1:
if (fw_dump.dump_registered == 1) { if (fw_dump.dump_registered == 1) {
/* Un-register Firmware-assisted dump */ /* Un-register Firmware-assisted dump */
fadump_unregister_dump(&fdm); fw_dump.ops->fadump_unregister(&fw_dump);
} }
/* Register Firmware-assisted dump */ /* Register Firmware-assisted dump */
ret = register_fadump(); ret = register_fadump();
...@@ -1530,7 +1394,8 @@ static int fadump_region_show(struct seq_file *m, void *private) ...@@ -1530,7 +1394,8 @@ static int fadump_region_show(struct seq_file *m, void *private)
fdm_ptr = fdm_active; fdm_ptr = fdm_active;
else { else {
mutex_unlock(&fadump_mutex); mutex_unlock(&fadump_mutex);
fdm_ptr = &fdm; fw_dump.ops->fadump_region_show(&fw_dump, m);
return 0;
} }
seq_printf(m, seq_printf(m,
...@@ -1651,7 +1516,7 @@ int __init setup_fadump(void) ...@@ -1651,7 +1516,7 @@ int __init setup_fadump(void)
} }
/* Initialize the kernel dump memory structure for FAD registration. */ /* Initialize the kernel dump memory structure for FAD registration. */
else if (fw_dump.reserve_dump_area_size) else if (fw_dump.reserve_dump_area_size)
init_fadump_mem_struct(&fdm, fw_dump.reserve_dump_area_start); fw_dump.ops->fadump_init_mem_struct(&fw_dump);
fadump_init_files(); fadump_init_files();
return 1; return 1;
......
...@@ -22,19 +22,151 @@ ...@@ -22,19 +22,151 @@
#include "rtas-fadump.h" #include "rtas-fadump.h"
static struct rtas_fadump_mem_struct fdm;
static void rtas_fadump_update_config(struct fw_dump *fadump_conf,
const struct rtas_fadump_mem_struct *fdm)
{
fadump_conf->boot_mem_dest_addr =
be64_to_cpu(fdm->rmr_region.destination_address);
fadump_conf->fadumphdr_addr = (fadump_conf->boot_mem_dest_addr +
fadump_conf->boot_memory_size);
}
static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf) static u64 rtas_fadump_init_mem_struct(struct fw_dump *fadump_conf)
{ {
return fadump_conf->reserve_dump_area_start; u64 addr = fadump_conf->reserve_dump_area_start;
memset(&fdm, 0, sizeof(struct rtas_fadump_mem_struct));
addr = addr & PAGE_MASK;
fdm.header.dump_format_version = cpu_to_be32(0x00000001);
fdm.header.dump_num_sections = cpu_to_be16(3);
fdm.header.dump_status_flag = 0;
fdm.header.offset_first_dump_section =
cpu_to_be32((u32)offsetof(struct rtas_fadump_mem_struct,
cpu_state_data));
/*
* Fields for disk dump option.
* We are not using disk dump option, hence set these fields to 0.
*/
fdm.header.dd_block_size = 0;
fdm.header.dd_block_offset = 0;
fdm.header.dd_num_blocks = 0;
fdm.header.dd_offset_disk_path = 0;
/* set 0 to disable an automatic dump-reboot. */
fdm.header.max_time_auto = 0;
/* Kernel dump sections */
/* cpu state data section. */
fdm.cpu_state_data.request_flag =
cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
fdm.cpu_state_data.source_data_type =
cpu_to_be16(RTAS_FADUMP_CPU_STATE_DATA);
fdm.cpu_state_data.source_address = 0;
fdm.cpu_state_data.source_len =
cpu_to_be64(fadump_conf->cpu_state_data_size);
fdm.cpu_state_data.destination_address = cpu_to_be64(addr);
addr += fadump_conf->cpu_state_data_size;
/* hpte region section */
fdm.hpte_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
fdm.hpte_region.source_data_type =
cpu_to_be16(RTAS_FADUMP_HPTE_REGION);
fdm.hpte_region.source_address = 0;
fdm.hpte_region.source_len =
cpu_to_be64(fadump_conf->hpte_region_size);
fdm.hpte_region.destination_address = cpu_to_be64(addr);
addr += fadump_conf->hpte_region_size;
/* RMA region section */
fdm.rmr_region.request_flag = cpu_to_be32(RTAS_FADUMP_REQUEST_FLAG);
fdm.rmr_region.source_data_type =
cpu_to_be16(RTAS_FADUMP_REAL_MODE_REGION);
fdm.rmr_region.source_address = cpu_to_be64(RMA_START);
fdm.rmr_region.source_len = cpu_to_be64(fadump_conf->boot_memory_size);
fdm.rmr_region.destination_address = cpu_to_be64(addr);
addr += fadump_conf->boot_memory_size;
rtas_fadump_update_config(fadump_conf, &fdm);
return addr;
} }
static int rtas_fadump_register(struct fw_dump *fadump_conf) static int rtas_fadump_register(struct fw_dump *fadump_conf)
{ {
return -EIO; unsigned int wait_time;
int rc, err = -EIO;
/* TODO: Add upper time limit for the delay */
do {
rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
NULL, FADUMP_REGISTER, &fdm,
sizeof(struct rtas_fadump_mem_struct));
wait_time = rtas_busy_delay_time(rc);
if (wait_time)
mdelay(wait_time);
} while (wait_time);
switch (rc) {
case 0:
pr_info("Registration is successful!\n");
fadump_conf->dump_registered = 1;
err = 0;
break;
case -1:
pr_err("Failed to register. Hardware Error(%d).\n", rc);
break;
case -3:
if (!is_fadump_boot_mem_contiguous())
pr_err("Can't have holes in boot memory area.\n");
else if (!is_fadump_reserved_mem_contiguous())
pr_err("Can't have holes in reserved memory area.\n");
pr_err("Failed to register. Parameter Error(%d).\n", rc);
err = -EINVAL;
break;
case -9:
pr_err("Already registered!\n");
fadump_conf->dump_registered = 1;
err = -EEXIST;
break;
default:
pr_err("Failed to register. Unknown Error(%d).\n", rc);
break;
}
return err;
} }
static int rtas_fadump_unregister(struct fw_dump *fadump_conf) static int rtas_fadump_unregister(struct fw_dump *fadump_conf)
{ {
return -EIO; unsigned int wait_time;
int rc;
/* TODO: Add upper time limit for the delay */
do {
rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
NULL, FADUMP_UNREGISTER, &fdm,
sizeof(struct rtas_fadump_mem_struct));
wait_time = rtas_busy_delay_time(rc);
if (wait_time)
mdelay(wait_time);
} while (wait_time);
if (rc) {
pr_err("Failed to un-register - unexpected error(%d).\n", rc);
return -EIO;
}
fadump_conf->dump_registered = 0;
return 0;
} }
static int rtas_fadump_invalidate(struct fw_dump *fadump_conf) static int rtas_fadump_invalidate(struct fw_dump *fadump_conf)
...@@ -54,6 +186,30 @@ static int __init rtas_fadump_process(struct fw_dump *fadump_conf) ...@@ -54,6 +186,30 @@ static int __init rtas_fadump_process(struct fw_dump *fadump_conf)
static void rtas_fadump_region_show(struct fw_dump *fadump_conf, static void rtas_fadump_region_show(struct fw_dump *fadump_conf,
struct seq_file *m) struct seq_file *m)
{ {
const struct rtas_fadump_mem_struct *fdm_ptr = &fdm;
const struct rtas_fadump_section *cpu_data_section;
cpu_data_section = &(fdm_ptr->cpu_state_data);
seq_printf(m, "CPU :[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
be64_to_cpu(cpu_data_section->destination_address),
be64_to_cpu(cpu_data_section->destination_address) +
be64_to_cpu(cpu_data_section->source_len) - 1,
be64_to_cpu(cpu_data_section->source_len),
be64_to_cpu(cpu_data_section->bytes_dumped));
seq_printf(m, "HPTE:[%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
be64_to_cpu(fdm_ptr->hpte_region.destination_address),
be64_to_cpu(fdm_ptr->hpte_region.destination_address) +
be64_to_cpu(fdm_ptr->hpte_region.source_len) - 1,
be64_to_cpu(fdm_ptr->hpte_region.source_len),
be64_to_cpu(fdm_ptr->hpte_region.bytes_dumped));
seq_printf(m, "DUMP: [%#016llx-%#016llx] %#llx bytes, Dumped: %#llx\n",
be64_to_cpu(fdm_ptr->rmr_region.destination_address),
be64_to_cpu(fdm_ptr->rmr_region.destination_address) +
be64_to_cpu(fdm_ptr->rmr_region.source_len) - 1,
be64_to_cpu(fdm_ptr->rmr_region.source_len),
be64_to_cpu(fdm_ptr->rmr_region.bytes_dumped));
} }
static void rtas_fadump_trigger(struct fadump_crash_info_header *fdh, static void rtas_fadump_trigger(struct fadump_crash_info_header *fdh,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment