Re: [PATCH v4 18/25] powernv/fadump: process architected register state data provided by firmware

2019-08-15 Thread Hari Bathini



On 14/08/19 10:45 PM, Mahesh J Salgaonkar wrote:
> On 2019-07-16 17:04:08 Tue, Hari Bathini wrote:
>> From: Hari Bathini 
>>
>> Firmware provides architected register state data at the time of crash.
>> Process this data and build CPU notes to append to ELF core.
>>
>> Signed-off-by: Hari Bathini 
>> Signed-off-by: Vasant Hegde 
>> ---
>>  arch/powerpc/kernel/fadump-common.h  |4 +
>>  arch/powerpc/platforms/powernv/opal-fadump.c |  197 
>> --
>>  arch/powerpc/platforms/powernv/opal-fadump.h |   39 +
>>  3 files changed, 228 insertions(+), 12 deletions(-)
>>
> [...]
>> @@ -430,6 +577,32 @@ int __init opal_fadump_dt_scan(struct fw_dump 
>> *fadump_conf, ulong node)
>>  return 1;
>>  }
>>  
>> +ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, );
>> +if ((ret != OPAL_SUCCESS) || !addr) {
>> +pr_err("Failed to get CPU metadata (%lld)\n", ret);
>> +return 1;
>> +}
>> +
>> +addr = be64_to_cpu(addr);
>> +pr_debug("CPU metadata addr: %llx\n", addr);
>> +
>> +opal_cpu_metadata = __va(addr);
>> +r_opal_cpu_metadata = (void *)addr;
>> +fadump_conf->cpu_state_data_version =
>> +be32_to_cpu(r_opal_cpu_metadata->cpu_data_version);
>> +if (fadump_conf->cpu_state_data_version !=
>> +HDAT_FADUMP_CPU_DATA_VERSION) {
>> +pr_err("CPU data format version (%lu) mismatch!\n",
>> +   fadump_conf->cpu_state_data_version);
>> +return 1;
>> +}

I think cpu data version mismatch check should still be done early on?

>> +fadump_conf->cpu_state_entry_size =
>> +be32_to_cpu(r_opal_cpu_metadata->cpu_data_size);
>> +fadump_conf->cpu_state_destination_addr =
>> +be64_to_cpu(r_opal_cpu_metadata->region[0].dest);
>> +fadump_conf->cpu_state_data_size =
>> +be64_to_cpu(r_opal_cpu_metadata->region[0].size);
>> +
> 
> opal_fadump_dt_scan isn't the right place to do this. Can you please move 
> above
> cpu related data processing to opal_fadump_build_cpu_notes() ?

I will move the above cpu related data processing to 
opal_fadump_build_cpu_notes().

Thanks
Hari



Re: [PATCH v4 18/25] powernv/fadump: process architected register state data provided by firmware

2019-08-14 Thread Mahesh J Salgaonkar
On 2019-07-16 17:04:08 Tue, Hari Bathini wrote:
> From: Hari Bathini 
> 
> Firmware provides architected register state data at the time of crash.
> Process this data and build CPU notes to append to ELF core.
> 
> Signed-off-by: Hari Bathini 
> Signed-off-by: Vasant Hegde 
> ---
>  arch/powerpc/kernel/fadump-common.h  |4 +
>  arch/powerpc/platforms/powernv/opal-fadump.c |  197 
> --
>  arch/powerpc/platforms/powernv/opal-fadump.h |   39 +
>  3 files changed, 228 insertions(+), 12 deletions(-)
> 
[...]
> @@ -430,6 +577,32 @@ int __init opal_fadump_dt_scan(struct fw_dump 
> *fadump_conf, ulong node)
>   return 1;
>   }
>  
> + ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, );
> + if ((ret != OPAL_SUCCESS) || !addr) {
> + pr_err("Failed to get CPU metadata (%lld)\n", ret);
> + return 1;
> + }
> +
> + addr = be64_to_cpu(addr);
> + pr_debug("CPU metadata addr: %llx\n", addr);
> +
> + opal_cpu_metadata = __va(addr);
> + r_opal_cpu_metadata = (void *)addr;
> + fadump_conf->cpu_state_data_version =
> + be32_to_cpu(r_opal_cpu_metadata->cpu_data_version);
> + if (fadump_conf->cpu_state_data_version !=
> + HDAT_FADUMP_CPU_DATA_VERSION) {
> + pr_err("CPU data format version (%lu) mismatch!\n",
> +fadump_conf->cpu_state_data_version);
> + return 1;
> + }
> + fadump_conf->cpu_state_entry_size =
> + be32_to_cpu(r_opal_cpu_metadata->cpu_data_size);
> + fadump_conf->cpu_state_destination_addr =
> + be64_to_cpu(r_opal_cpu_metadata->region[0].dest);
> + fadump_conf->cpu_state_data_size =
> + be64_to_cpu(r_opal_cpu_metadata->region[0].size);
> +

opal_fadump_dt_scan isn't the right place to do this. Can you please move above
cpu related data processing to opal_fadump_build_cpu_notes() ?

Thanks,
-Mahesh.

>   pr_info("Firmware-assisted dump is active.\n");
>   fadump_conf->dump_active = 1;
>   opal_fadump_get_config(fadump_conf, r_opal_fdm_active);



[PATCH v4 18/25] powernv/fadump: process architected register state data provided by firmware

2019-07-16 Thread Hari Bathini
From: Hari Bathini 

Firmware provides architected register state data at the time of crash.
Process this data and build CPU notes to append to ELF core.

Signed-off-by: Hari Bathini 
Signed-off-by: Vasant Hegde 
---
 arch/powerpc/kernel/fadump-common.h  |4 +
 arch/powerpc/platforms/powernv/opal-fadump.c |  197 --
 arch/powerpc/platforms/powernv/opal-fadump.h |   39 +
 3 files changed, 228 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/kernel/fadump-common.h 
b/arch/powerpc/kernel/fadump-common.h
index 968745a..2dd0d9d 100644
--- a/arch/powerpc/kernel/fadump-common.h
+++ b/arch/powerpc/kernel/fadump-common.h
@@ -121,7 +121,11 @@ struct fw_dump {
 */
unsigned long   preserv_area_start;
 
+   unsigned long   cpu_state_destination_addr;
+   unsigned long   cpu_state_data_version;
+   unsigned long   cpu_state_entry_size;
unsigned long   cpu_state_data_size;
+
unsigned long   hpte_region_size;
 
unsigned long   boot_memory_size;
diff --git a/arch/powerpc/platforms/powernv/opal-fadump.c 
b/arch/powerpc/platforms/powernv/opal-fadump.c
index dffc0e7..479967c 100644
--- a/arch/powerpc/platforms/powernv/opal-fadump.c
+++ b/arch/powerpc/platforms/powernv/opal-fadump.c
@@ -27,6 +27,7 @@
 #include "opal-fadump.h"
 
 static const struct opal_fadump_mem_struct *opal_fdm_active;
+static const struct opal_mpipl_fadump *opal_cpu_metadata;
 static struct opal_fadump_mem_struct *opal_fdm;
 
 static void opal_fadump_update_config(struct fw_dump *fadump_conf,
@@ -233,15 +234,115 @@ static int opal_fadump_invalidate_fadump(struct fw_dump 
*fadump_conf)
return 0;
 }
 
+static inline void opal_fadump_set_regval_regnum(struct pt_regs *regs,
+u32 reg_type, u32 reg_num,
+u64 reg_val)
+{
+   if (reg_type == HDAT_FADUMP_REG_TYPE_GPR) {
+   if (reg_num < 32)
+   regs->gpr[reg_num] = reg_val;
+   return;
+   }
+
+   switch (reg_num) {
+   case SPRN_CTR:
+   regs->ctr = reg_val;
+   break;
+   case SPRN_LR:
+   regs->link = reg_val;
+   break;
+   case SPRN_XER:
+   regs->xer = reg_val;
+   break;
+   case SPRN_DAR:
+   regs->dar = reg_val;
+   break;
+   case SPRN_DSISR:
+   regs->dsisr = reg_val;
+   break;
+   case HDAT_FADUMP_REG_ID_NIP:
+   regs->nip = reg_val;
+   break;
+   case HDAT_FADUMP_REG_ID_MSR:
+   regs->msr = reg_val;
+   break;
+   case HDAT_FADUMP_REG_ID_CCR:
+   regs->ccr = reg_val;
+   break;
+   }
+}
+
+static inline void opal_fadump_read_regs(char *bufp, unsigned int regs_cnt,
+unsigned int reg_entry_size,
+struct pt_regs *regs)
+{
+   int i;
+   struct hdat_fadump_reg_entry *reg_entry;
+
+   memset(regs, 0, sizeof(struct pt_regs));
+
+   for (i = 0; i < regs_cnt; i++, bufp += reg_entry_size) {
+   reg_entry = (struct hdat_fadump_reg_entry *)bufp;
+   opal_fadump_set_regval_regnum(regs,
+ be32_to_cpu(reg_entry->reg_type),
+ be32_to_cpu(reg_entry->reg_num),
+ be64_to_cpu(reg_entry->reg_val));
+   }
+}
+
+static inline bool __init is_thread_core_inactive(u8 core_state)
+{
+   bool is_inactive = false;
+
+   if (core_state == HDAT_FADUMP_CORE_INACTIVE)
+   is_inactive = true;
+
+   return is_inactive;
+}
+
 /*
  * Convert CPU state data saved at the time of crash into ELF notes.
+ *
+ * Each register entry is of 16 bytes, A numerical identifier along with
+ * a GPR/SPR flag in the first 8 bytes and the register value in the next
+ * 8 bytes. For more details refer to F/W documentation.
  */
 static int __init opal_fadump_build_cpu_notes(struct fw_dump *fadump_conf)
 {
u32 num_cpus, *note_buf;
struct fadump_crash_info_header *fdh = NULL;
+   struct hdat_fadump_thread_hdr *thdr;
+   unsigned long addr;
+   u32 thread_pir;
+   char *bufp;
+   struct pt_regs regs;
+   unsigned int size_of_each_thread;
+   unsigned int regs_offset, regs_cnt, reg_esize;
+   int i;
+
+   if ((fadump_conf->cpu_state_destination_addr == 0) ||
+   (fadump_conf->cpu_state_entry_size == 0)) {
+   pr_err("CPU state data not available for processing!\n");
+   return -ENODEV;
+   }
+
+   size_of_each_thread = fadump_conf->cpu_state_entry_size;
+   num_cpus = (fadump_conf->cpu_state_data_size / size_of_each_thread);
+
+   addr = fadump_conf->cpu_state_destination_addr;
+   bufp = __va(addr);