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: Hari Bathini <hbathini@linux.ibm.com> Reviewed-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/156821332856.5656.16380417702046411631.stgit@hbathini.in.ibm.com
This commit is contained in:
parent
d3833a7010
commit
41a65d1618
|
@ -89,7 +89,9 @@ struct fw_dump {
|
|||
|
||||
unsigned long cpu_state_data_size;
|
||||
unsigned long hpte_region_size;
|
||||
|
||||
unsigned long boot_memory_size;
|
||||
u64 boot_mem_dest_addr;
|
||||
|
||||
unsigned long fadumphdr_addr;
|
||||
unsigned long cpu_notes_buf_vaddr;
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include "../platforms/pseries/rtas-fadump.h"
|
||||
|
||||
static struct fw_dump fw_dump;
|
||||
static struct rtas_fadump_mem_struct fdm;
|
||||
static const struct rtas_fadump_mem_struct *fdm_active;
|
||||
|
||||
static DEFINE_MUTEX(fadump_mutex);
|
||||
|
@ -229,61 +228,6 @@ static void fadump_show_config(void)
|
|||
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
|
||||
*
|
||||
|
@ -546,61 +490,6 @@ static int __init early_fadump_reserve_mem(char *p)
|
|||
}
|
||||
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)
|
||||
{
|
||||
struct fadump_crash_info_header *fdh = NULL;
|
||||
|
@ -643,8 +532,7 @@ void crash_fadump(struct pt_regs *regs, const char *str)
|
|||
|
||||
fdh->online_mask = *cpu_online_mask;
|
||||
|
||||
/* Call ibm,os-term rtas call to trigger firmware assisted dump */
|
||||
rtas_os_term((char *)str);
|
||||
fw_dump.ops->fadump_trigger(fdh, str);
|
||||
}
|
||||
|
||||
#define GPR_MASK 0xffffff0000000000
|
||||
|
@ -1129,7 +1017,7 @@ static int fadump_setup_crash_memory_ranges(void)
|
|||
static inline unsigned long fadump_relocate(unsigned long paddr)
|
||||
{
|
||||
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
|
||||
return paddr;
|
||||
}
|
||||
|
@ -1202,7 +1090,7 @@ static int fadump_create_elfcore_headers(char *bufp)
|
|||
* to the specified destination_address. Hence set
|
||||
* 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;
|
||||
|
@ -1254,7 +1142,8 @@ static int register_fadump(void)
|
|||
if (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. */
|
||||
addr = init_fadump_header(addr);
|
||||
vaddr = __va(addr);
|
||||
|
@ -1263,34 +1152,8 @@ static int register_fadump(void)
|
|||
fadump_create_elfcore_headers(vaddr);
|
||||
|
||||
/* register the future kernel dump with firmware. */
|
||||
return register_fw_dump(&fdm);
|
||||
}
|
||||
|
||||
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;
|
||||
pr_debug("Registering for firmware-assisted kernel dump...\n");
|
||||
return fw_dump.ops->fadump_register(&fw_dump);
|
||||
}
|
||||
|
||||
static int fadump_invalidate_dump(const struct rtas_fadump_mem_struct *fdm)
|
||||
|
@ -1328,7 +1191,7 @@ void fadump_cleanup(void)
|
|||
fadump_invalidate_dump(fdm_active);
|
||||
} else if (fw_dump.dump_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();
|
||||
}
|
||||
}
|
||||
|
@ -1433,7 +1296,7 @@ static void fadump_invalidate_release_mem(void)
|
|||
fadump_free_cpu_notes_buf();
|
||||
|
||||
/* 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,
|
||||
|
@ -1498,12 +1361,13 @@ static ssize_t fadump_register_store(struct kobject *kobj,
|
|||
goto unlock_out;
|
||||
}
|
||||
/* 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;
|
||||
case 1:
|
||||
if (fw_dump.dump_registered == 1) {
|
||||
/* Un-register Firmware-assisted dump */
|
||||
fadump_unregister_dump(&fdm);
|
||||
fw_dump.ops->fadump_unregister(&fw_dump);
|
||||
}
|
||||
/* Register Firmware-assisted dump */
|
||||
ret = register_fadump();
|
||||
|
@ -1530,7 +1394,8 @@ static int fadump_region_show(struct seq_file *m, void *private)
|
|||
fdm_ptr = fdm_active;
|
||||
else {
|
||||
mutex_unlock(&fadump_mutex);
|
||||
fdm_ptr = &fdm;
|
||||
fw_dump.ops->fadump_region_show(&fw_dump, m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
seq_printf(m,
|
||||
|
@ -1651,7 +1516,7 @@ int __init setup_fadump(void)
|
|||
}
|
||||
/* Initialize the kernel dump memory structure for FAD registration. */
|
||||
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();
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -22,19 +22,151 @@
|
|||
|
||||
#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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
@ -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,
|
||||
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,
|
||||
|
|
Loading…
Reference in New Issue