pseries/fadump: define RTAS register/un-register callback functions
authorHari Bathini <hbathini@linux.ibm.com>
Wed, 11 Sep 2019 14:48:57 +0000 (20:18 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 13 Sep 2019 14:04:42 +0000 (00:04 +1000)
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
arch/powerpc/include/asm/fadump-internal.h
arch/powerpc/kernel/fadump.c
arch/powerpc/platforms/pseries/rtas-fadump.c

index 8ecd234..8c0eb0f 100644 (file)
@@ -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;
index aa342ee..3cf6210 100644 (file)
@@ -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;
index 9efe7b1..1daa29f 100644 (file)
 
 #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,