With kernel commit 0990d836ce "s390/debug: debug feature version 3" the
__debug_entry structure has been modified by:
  - removing redundant union
  - expanding microseconds timestamp to 60 bits and storing it in the
    absolute Unix time format taking Epoch Index into account
  - expanding cpuid field to 16 bits
Current crash patch aims to:
  - define debug_entry_v3_t data type for new debug entry structure
  and process V3 debug entries accordingly
  - adjust debug entries header output by setting minimum width for
    cpuid to 4 digits and expanding function name width to 26 characters
  - adjust output alignment for the header and debug entries
  - minor code cleanup

Signed-off-by: Mikhail Zaslonko <zaslo...@linux.ibm.com>
---
 s390dbf.c | 130 +++++++++++++++++++++++++++++++-----------------------
 1 file changed, 74 insertions(+), 56 deletions(-)

diff --git a/s390dbf.c b/s390dbf.c
index 232ceb8..5f53170 100644
--- a/s390dbf.c
+++ b/s390dbf.c
@@ -165,6 +165,7 @@ static inline int set_cmd_flags(command_t *cmd, int flags, 
char *extraops)
        return 0;
 }
 
+#define USEC_PER_SEC 1000000L
 /* Time of day clock value for 1970/01/01 */
 #define TOD_UNIX_EPOCH (0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096))
 /* Time of day clock value for 1970/01/01 in usecs */
@@ -180,8 +181,8 @@ static inline void kl_s390tod_to_timeval(uint64_t todval, 
struct timeval *xtime)
        todval_us += tod_clock_base_us;
        /* Subtract EPOCH that we get time in usec since 1970 */
        todval_us -= TOD_UNIX_EPOCH_US;
-       xtime->tv_sec  = todval_us / 1000000;
-       xtime->tv_usec = todval_us % 1000000;
+       xtime->tv_sec  = todval_us / USEC_PER_SEC;
+       xtime->tv_usec = todval_us % USEC_PER_SEC;
 }
 
 static inline int kl_struct_len(char* struct_name)
@@ -227,6 +228,7 @@ static inline kaddr_t kl_funcaddr(kaddr_t addr)
 
 #define DBF_VERSION_V1 1
 #define DBF_VERSION_V2 2
+#define DBF_VERSION_V3 3
 #define PAGE_SIZE 4096
 #define DEBUG_MAX_VIEWS            10 /* max number of views in proc fs */
 #define DEBUG_MAX_PROCF_LEN    64 /* max length for a proc file name */
@@ -238,8 +240,9 @@ static inline kaddr_t kl_funcaddr(kaddr_t addr)
 typedef struct debug_view_s debug_view_t;
 
 /* struct to hold contents of struct __debug_entry from dump
+ * for DBF_VERSION_V1 and DBF_VERSION_V2
  */
-typedef struct debug_entry_s{
+typedef struct debug_entry_v1_s{
        union {
                struct {
                        unsigned long long clock:52;
@@ -251,9 +254,16 @@ typedef struct debug_entry_s{
                unsigned long long stck;
        } id;
        kaddr_t caller; /* changed from void* to kaddr_t */
-} __attribute__((packed)) debug_entry_t;
-/* typedef struct __debug_entry debug_entry_t; */
+} __attribute__((packed)) debug_entry_v1_t;
 
+/* for DBF_VERSION_V3 */
+typedef struct debug_entry_v3_s{
+       unsigned long long clock:60;
+       unsigned long long exception:1;
+       unsigned long long level:3;
+       kaddr_t caller; /* changed from void* to kaddr_t */
+       unsigned short cpuid;
+} __attribute__((packed)) debug_entry_v3_t;
 
 static unsigned int dbf_version;
 
@@ -284,7 +294,7 @@ typedef struct debug_info_s {
 /* functions to generate dbf output
  */
 typedef int (debug_header_proc_t) (debug_info_t* id, debug_view_t* view,
-                                  int area, debug_entry_t* entry,
+                                  int area, void* entry,
                                   char* out_buf);
 typedef int (debug_format_proc_t) (debug_info_t* id, debug_view_t* view,
                                   char* out_buf, const char* in_buf);
@@ -322,35 +332,45 @@ EBCASC(char *inout, size_t len)
  */
 static int
 dflt_header_fn(debug_info_t * id, debug_view_t *view,
-              int area, debug_entry_t * entry, char *out_buf)
+              int area, void *entry, char *out_buf)
 {
        struct timeval time_val;
-       unsigned long long time;
-       char *except_str;
-       kaddr_t caller;
        int rc = 0;
+       unsigned long long time;
+       unsigned short level = 0, cpuid = 0;
+       char *except_str = "-";
+       kaddr_t caller = 0;
        char *caller_name;
+       int name_width = 26;
        int offset;
        char caller_buf[30];
-       unsigned int level;
        syment_t *caller_sym;
-       debug_entry_t lentry; /* store byte swapped values of entry */
 
-       lentry.id.stck = KL_GET_UINT64(&entry->id);
-       lentry.caller = KL_GET_PTR(&entry->caller);
-       level = lentry.id.fields.level;
-       time = lentry.id.stck;
-
-       kl_s390tod_to_timeval(time, &time_val);
+       switch (dbf_version) {
+       case DBF_VERSION_V1:
+       case DBF_VERSION_V2:
+               level = ((debug_entry_v1_t *) entry)->id.fields.level;
+               cpuid = ((debug_entry_v1_t *) entry)->id.fields.cpuid;
+               time = ((debug_entry_v1_t *) entry)->id.stck;
+               if (((debug_entry_v1_t *) entry)->id.fields.exception)
+                       except_str = "*";
+               caller = ((debug_entry_v1_t *) entry)->caller;
+               kl_s390tod_to_timeval(time, &time_val);
+               break;
+       case DBF_VERSION_V3:
+               level = ((debug_entry_v3_t *) entry)->level;
+               cpuid = ((debug_entry_v3_t *) entry)->cpuid;
+               time = ((debug_entry_v3_t *) entry)->clock;
+               if (((debug_entry_v3_t *) entry)->exception)
+                       except_str = "*";
+               caller = ((debug_entry_v3_t *) entry)->caller;
+               time_val.tv_sec  = time / USEC_PER_SEC;
+               time_val.tv_usec = time % USEC_PER_SEC;
+               break;
+       }
 
-       if (lentry.id.fields.exception)
-               except_str = "*";
-       else
-               except_str = "-";
-       caller = lentry.caller;
-       if(KL_ARCH == KL_ARCH_S390){
+       if(KL_ARCH == KL_ARCH_S390)
                caller &= 0x7fffffff;
-       }
        caller_sym = kl_lkup_symaddr(caller);
        if(caller_sym){
                caller_name = caller_sym->s_name;
@@ -361,20 +381,12 @@ dflt_header_fn(debug_info_t * id, debug_view_t *view,
                caller_name = caller_buf;
                offset = 0;
        }
+       rc += sprintf(out_buf,
+             "%02i %011lu:%06lu %1u %1s %04i <%-*s+%04i>  ",
+             area, time_val.tv_sec, time_val.tv_usec, level,
+             except_str, cpuid,
+             name_width, caller_name, offset);
 
-       if(KL_ARCH == KL_ARCH_S390X){
-               rc += sprintf(out_buf, 
-                             "%02i %011lu:%06lu %1u %1s %02i <%20s+%04i>  ",
-                             area, time_val.tv_sec, time_val.tv_usec, level,
-                             except_str, entry->id.fields.cpuid, caller_name,
-                             offset);
-       } else {
-               rc += sprintf(out_buf,
-                             "%02i %011lu:%06lu %1u %1s %02i <%-20s+%04i>  ",
-                             area, time_val.tv_sec, time_val.tv_usec, level,
-                             except_str, lentry.id.fields.cpuid, caller_name,
-                             offset);
-       }
        return rc;
 }
 
@@ -539,9 +551,9 @@ prolog_fn(debug_info_t * id,
 {
        int rc = 0;
 
-       rc = sprintf(out_buf, "AREA TIME LEVEL EXCEPTION CP CALLING FUNCTION"
-                    "   + OFFSET  DATA\n==================================="
-                    "=======================================\n");
+       rc = sprintf(out_buf, "AREA TIME LEVEL EXCEPTION CP   CALLING FUNCTION"
+                    " + OFFSET          DATA\n==============================="
+                    "===========================================\n");
        return rc;
 }
 
@@ -663,10 +675,10 @@ debug_view_t sprintf_view = {
 };
 
 
-static debug_entry_t *
-debug_find_oldest_entry(debug_entry_t *entries, int num, int entry_size)
+static debug_entry_v1_t *
+debug_find_oldest_entry(debug_entry_v1_t *entries, int num, int entry_size)
 {
-       debug_entry_t *result, *current;
+       debug_entry_v1_t *result, *current;
        int i;
        uint64_t clock1, clock2;
 
@@ -681,7 +693,7 @@ debug_find_oldest_entry(debug_entry_t *entries, int num, 
int entry_size)
                clock2 = KL_GET_UINT64(&clock2);
                if (clock1 < clock2)
                        result = current;
-               current = (debug_entry_t *) ((char *) current + entry_size);
+               current = (debug_entry_v1_t *) ((char *) current + entry_size);
        }
        return result;
 }
@@ -697,7 +709,7 @@ debug_format_output_v1(debug_info_t * debug_area, 
debug_view_t *view,
 {
        int i, j, len;
        int nr_of_entries;
-       debug_entry_t *act_entry, *last_entry;
+       debug_entry_v1_t *act_entry, *last_entry;
        char *act_entry_data;
        char buf[2048];
        size_t items ATTRIBUTE_UNUSED;
@@ -720,7 +732,7 @@ debug_format_output_v1(debug_info_t * debug_area, 
debug_view_t *view,
                act_entry = debug_find_oldest_entry(debug_area->areas[i],
                                                    nr_of_entries,
                                                    debug_area->entry_size);
-               last_entry = (debug_entry_t *) ((char *) debug_area->areas[i] +
+               last_entry = (debug_entry_v1_t *) ((char *) 
debug_area->areas[i] +
                             (PAGE_SIZE << debug_area->page_order) -
                             debug_area->entry_size);
                for (j = 0; j < nr_of_entries; j++) {
@@ -740,7 +752,7 @@ debug_format_output_v1(debug_info_t * debug_area, 
debug_view_t *view,
                                memset(buf, 0, 2048); 
                        }
                        act_entry =
-                           (debug_entry_t *) (((char *) act_entry) +
+                           (debug_entry_v1_t *) (((char *) act_entry) +
                                               debug_area->entry_size);
                        if (act_entry > last_entry)
                                act_entry = debug_area->areas[i];
@@ -759,7 +771,7 @@ debug_format_output_v2(debug_info_t * debug_area,
                    debug_view_t *view, FILE * ofp)
 {
        int i, j, k, len;
-       debug_entry_t *act_entry;
+       void *act_entry;
        char *act_entry_data;
        char buf[2048];
        size_t items ATTRIBUTE_UNUSED;
@@ -783,7 +795,11 @@ debug_format_output_v2(debug_info_t * debug_area,
                        act_entry = debug_area->areas_v2[i][j];
                        for (k = 0; k < nr_entries_per_page; k++) {
                                act_entry_data = (char*)act_entry + dbe_size;
-                               if (act_entry->id.stck == 0)
+                               if (dbf_version == DBF_VERSION_V3 &&
+                                   ((debug_entry_v3_t *) act_entry)->clock == 
0)
+                                       break;  /* empty entry */
+                               else if (dbf_version < DBF_VERSION_V3 &&
+                                   ((debug_entry_v1_t *) act_entry)->id.stck 
== 0)
                                        break;  /* empty entry */
                                if (view->header_proc) {
                                        len = view->header_proc(debug_area, 
@@ -797,8 +813,8 @@ debug_format_output_v2(debug_info_t * debug_area,
                                        items = fwrite(buf,len, 1, ofp);
                                        memset(buf, 0, 2048); 
                                }
-                               act_entry = (debug_entry_t *) (((char *) 
-                                       act_entry) + debug_area->entry_size);
+                               act_entry = ((char *) act_entry) +
+                                       debug_area->entry_size;
                        }
                }
        }
@@ -905,7 +921,7 @@ debug_get_areas_v1(debug_info_t* db_info, void* k_dbi)
                mem_pos = KL_ULONG(k_dbi,"debug_info","areas");
                for (i = 0; i < db_info->nr_areas; i++) {
                dbe_addr = KL_VREAD_PTR(mem_pos);
-               db_info->areas[i] = (debug_entry_t *) malloc(area_size);
+               db_info->areas[i] = (debug_entry_v1_t *) malloc(area_size);
                /* read raw data for debug area */
                GET_BLOCK(dbe_addr, area_size, db_info->areas[i]);
                mem_pos += KL_NBPW;
@@ -1328,11 +1344,13 @@ s390dbf_cmd(command_t * cmd)
 
        dbf_version = KL_VREAD_UINT32(dbf_version_sym->s_addr);
 
-       if ((dbf_version != DBF_VERSION_V1) && (dbf_version != DBF_VERSION_V2)){
+       if ((dbf_version != DBF_VERSION_V1) &&
+           (dbf_version != DBF_VERSION_V2) &&
+           (dbf_version != DBF_VERSION_V3)) {
                fprintf(cmd->efp,"lcrash does not support the"
                        " debug feature version of the dump kernel:\n");
-               fprintf(cmd->efp,"DUMP: %i SUPPORTED: %i and %i\n",
-                       dbf_version, DBF_VERSION_V1, DBF_VERSION_V2);
+               fprintf(cmd->efp,"DUMP: %i SUPPORTED: %i, %i and %i\n",
+                       dbf_version, DBF_VERSION_V1, DBF_VERSION_V2, 
DBF_VERSION_V3);
                return -1;
        }
 
-- 
2.17.1

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to