Re: s390dbf support for crash
by Michael Holzheu
Hi Dave!
anderson(a)redhat.com wrote on 08/14/2006 04:58:11 PM:
> This looks fine to me. Do me one favor, though, and run the build
> through "make Warn"? There will be a couple minor items to clean
> up in s390dbf.c.
No problem, thanks for the hint! Here comes the updated version without
warings.
BTW: There are a couple of warnings in other files, which should probably
be fixed, too. I use gcc 4.1.0 for our build on s390(x). I hope that I find
time to fix the other warnings later.
Thanks
Michael
---
Makefile | 7
defs.h | 6
global_data.c | 3
s390dbf.c | 1339 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 1353 insertions(+), 2 deletions(-)
diff -Naur crash-4.0-3.1/Makefile crash-4.0-3.1-s390dbf/Makefile
--- crash-4.0-3.1/Makefile 2006-08-04 17:24:00.000000000 +0200
+++ crash-4.0-3.1-s390dbf/Makefile 2006-08-14 17:17:23.000000000 +0200
@@ -73,7 +73,7 @@
CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \
kernel.c test.c gdb_interface.c configure.c net.c dev.c \
- alpha.c x86.c ppc.c ia64.c s390.c s390x.c ppc64.c x86_64.c \
+ alpha.c x86.c ppc.c ia64.c s390.c s390x.c s390dbf.c ppc64.c x86_64.c \
extensions.c remote.c va_server.c va_server_v1.c symbols.c cmdline.c \
lkcd_common.c lkcd_v1.c lkcd_v2_v3.c lkcd_v5.c lkcd_v7.c lkcd_v8.c\
lkcd_fix_mem.c s390_dump.c lkcd_x86_trace.c \
@@ -85,7 +85,7 @@
OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \
build_data.o kernel.o test.o gdb_interface.o net.o dev.o \
- alpha.o x86.o ppc.o ia64.o s390.o s390x.o ppc64.o x86_64.o \
+ alpha.o x86.o ppc.o ia64.o s390.o s390x.o s390dbf.o ppc64.o x86_64.o \
extensions.o remote.o va_server.o va_server_v1.o symbols.o cmdline.o \
lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \
lkcd_fix_mem.o s390_dump.o netdump.o diskdump.o xendump.o \
@@ -364,6 +364,9 @@
s390x.o: ${GENERIC_HFILES} ${IBM_HFILES} s390x.c
cc -c ${CFLAGS} s390x.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+s390dbf.o: ${GENERIC_HFILES} ${IBM_HFILES} s390dbf.c
+ cc -c ${CFLAGS} s390dbf.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+
s390_dump.o: ${GENERIC_HFILES} ${IBM_HFILES} s390_dump.c
cc -c ${CFLAGS} s390_dump.c ${WARNING_OPTIONS} ${WARNING_ERROR}
diff -Naur crash-4.0-3.1/defs.h crash-4.0-3.1-s390dbf/defs.h
--- crash-4.0-3.1/defs.h 2006-08-04 17:24:00.000000000 +0200
+++ crash-4.0-3.1-s390dbf/defs.h 2006-08-14 17:17:27.000000000 +0200
@@ -2822,6 +2822,9 @@
void cmd_gdb(void); /* gdb_interface.c */
void cmd_net(void); /* net.c */
void cmd_extend(void); /* extensions.c */
+#if defined(S390) || defined(S390X)
+void cmd_s390dbf(void);
+#endif
/*
* main.c
@@ -3239,6 +3242,9 @@
extern char *help_waitq[];
extern char *help_whatis[];
extern char *help_wr[];
+#if defined(S390) || defined(S390X)
+extern char *help_s390dbf[];
+#endif
/*
* task.c
diff -Naur crash-4.0-3.1/global_data.c crash-4.0-3.1-s390dbf/global_data.c
--- crash-4.0-3.1/global_data.c 2006-08-04 17:24:00.000000000 +0200
+++ crash-4.0-3.1-s390dbf/global_data.c 2006-08-14 17:17:32.000000000 +0200
@@ -117,6 +117,9 @@
{"waitq", cmd_waitq, help_waitq, REFRESH_TASK_TABLE},
{"whatis", cmd_whatis, help_whatis, 0},
{"wr", cmd_wr, help_wr, 0},
+#if defined(S390) || defined(S390X)
+ {"s390dbf", cmd_s390dbf, help_s390dbf, 0},
+#endif
{(char *)NULL}
};
diff -Naur crash-4.0-3.1/s390dbf.c crash-4.0-3.1-s390dbf/s390dbf.c
--- crash-4.0-3.1/s390dbf.c 1970-01-01 01:00:00.000000000 +0100
+++ crash-4.0-3.1-s390dbf/s390dbf.c 2006-08-14 17:17:40.000000000 +0200
@@ -0,0 +1,1339 @@
+/*
+ * s390 debug feature command for crash
+ *
+ * Copyright (C) IBM Corp. 2006
+ * Author(s): Michael Holzheu <holzheu(a)de.ibm.com>
+ */
+
+#if defined(S390) || defined(S390X)
+
+#include "defs.h"
+#include <iconv.h>
+#include <ctype.h>
+
+/*
+ * Compat layer to integrate lcrash commands into crash
+ * Maps lcrash API to crash functions
+ */
+
+#define KL_NBPW sizeof(long)
+#define KL_ERRORFP stderr
+#define MAX_ARGS 128
+#define MAX_CMDLINE 256
+
+#define C_FALSE 0x00000001 /* Command takes no arguments */
+#define C_TRUE 0x00000002 /* Command requires arguments */
+#define C_ALL 0x00000004 /* All elements */
+#define C_PERM 0x00000008 /* Allocate perminant blocks */
+#define C_TEMP 0x00000000 /* For completeness */
+#define C_FULL 0x00000010 /* Full output */
+#define C_LIST 0x00000020 /* List items */
+#define C_NEXT 0x00000040 /* Follow links */
+#define C_WRITE 0x00000080 /* Write output to file */
+#define C_NO_OPCHECK 0x00000100 /* Don't reject bad cmd line options */
+#define C_ITER 0x00000200 /* set iteration threshold */
+
+#define C_LFLG_SHFT 12
+
+#define KL_ARCH_S390 0
+#define KL_ARCH_S390X 1
+#ifdef __s390x__
+#define KL_ARCH KL_ARCH_S390X
+#define FMTPTR "l"
+#define KL_PTRSZ 8
+#else
+#define KL_ARCH KL_ARCH_S390
+#define FMTPTR "ll"
+#define KL_PTRSZ 4
+#endif
+
+typedef unsigned long uaddr_t;
+typedef unsigned long kaddr_t;
+
+typedef struct _syment {
+ char *s_name;
+ kaddr_t s_addr;
+} syment_t;
+
+typedef struct option_s {
+ struct option_s *op_next;
+ char op_char;
+ char *op_arg;
+} option_t;
+
+typedef struct command_s {
+ int flags;
+ char cmdstr[MAX_CMDLINE];
+ char *command;
+ char *cmdline;
+ option_t *options;
+ int nargs;
+ char *args[MAX_ARGS];
+ char *pipe_cmd;
+ FILE *ofp;
+ FILE *efp;
+} command_t;
+
+static inline syment_t* kl_lkup_symaddr(kaddr_t addr)
+{
+ static syment_t sym;
+ struct syment *crash_sym;
+
+ crash_sym = value_search(addr, &sym.s_addr);
+ if (!crash_sym)
+ return NULL;
+ sym.s_name = crash_sym->name;
+ return &sym;
+}
+
+static inline syment_t* kl_lkup_symname(char* name)
+{
+ static syment_t sym;
+ sym.s_addr = symbol_value(name);
+ sym.s_name = NULL;
+ if(!sym.s_addr)
+ return NULL;
+ else
+ return &sym;
+}
+
+static inline void GET_BLOCK(kaddr_t addr, int size, void* ptr)
+{
+ readmem(addr, KVADDR,ptr,size,"GET_BLOCK",FAULT_ON_ERROR);
+}
+
+static inline kaddr_t KL_VREAD_PTR(kaddr_t addr)
+{
+ unsigned long ptr;
+ readmem(addr, KVADDR,&ptr,sizeof(ptr),"GET_BLOCK",FAULT_ON_ERROR);
+ return (kaddr_t)ptr;
+}
+
+static inline uint32_t KL_GET_UINT32(void* ptr)
+{
+ return *((uint32_t*)ptr);
+}
+
+static inline uint64_t KL_GET_UINT64(void* ptr)
+{
+ return *((uint64_t*)ptr);
+}
+
+static inline kaddr_t KL_GET_PTR(void* ptr)
+{
+ return *((kaddr_t*)ptr);
+}
+
+static inline void* K_PTR(void* addr, char* struct_name, char* member_name)
+{
+ return addr+MEMBER_OFFSET(struct_name,member_name);
+}
+
+static inline uint32_t KL_UINT(void* ptr, char* struct_name, char* member_name)
+{
+ return (uint32_t) ULONG(ptr+MEMBER_OFFSET(struct_name,member_name));
+}
+
+static inline uint32_t KL_VREAD_UINT32(kaddr_t addr)
+{
+ uint32_t rc;
+ readmem(addr, KVADDR,&rc,sizeof(rc),"KL_VREAD_UINT32",FAULT_ON_ERROR);
+ return rc;
+}
+
+static inline uint32_t KL_INT(void* ptr, char* struct_name, char* member_name)
+{
+ return UINT(ptr+MEMBER_OFFSET(struct_name,member_name));
+}
+
+static inline int set_cmd_flags(command_t *cmd, int flags, char *extraops)
+{
+ return 0;
+}
+
+static inline void kl_s390tod_to_timeval(uint64_t todval, struct timeval *xtime)
+{
+ todval -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
+
+ todval >>= 12;
+ xtime->tv_sec = todval / 1000000;
+ xtime->tv_usec = todval % 1000000;
+}
+
+static inline int kl_struct_len(char* struct_name)
+{
+ return STRUCT_SIZE(struct_name);
+}
+
+static inline kaddr_t kl_funcaddr(kaddr_t addr)
+{
+ struct syment *crash_sym;
+
+ crash_sym = value_search(addr, &addr);
+ if (!crash_sym)
+ return -1;
+ else
+ return crash_sym->value;
+}
+
+#define CMD_USAGE(cmd, s) \
+ fprintf(cmd->ofp, "Usage: %s %s\n", cmd->command, s); \
+ fprintf(cmd->ofp, "Enter \"help %s\" for details.\n",cmd->command);
+
+/*
+ * s390 debug feature implementation
+ */
+
+#ifdef DBF_DYNAMIC_VIEWS /* views defined in shared libs */
+#include <dlfcn.h>
+#endif
+
+/* Local flags
+ */
+
+#define LOAD_FLAG (1 << C_LFLG_SHFT)
+#define VIEWS_FLAG (2 << C_LFLG_SHFT)
+
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+/* Stuff which has to match with include/asm-s390/debug.h */
+
+#define DBF_VERSION_V1 1
+#define DBF_VERSION_V2 2
+#define PAGE_SIZE 4096
+#define DEBUG_MAX_VIEWS 10 /* max number of views in proc fs */
+#define DEBUG_MAX_PROCF_LEN 16 /* max length for a proc file name */
+#define DEBUG_SPRINTF_MAX_ARGS 10
+
+/* define debug-structures for lcrash */
+#define DEBUG_DATA(entry) (char*)(entry + 1)
+
+typedef struct debug_view_s debug_view_t;
+
+/* struct to hold contents of struct __debug_entry from dump
+ */
+typedef struct debug_entry_s{
+ union {
+ struct {
+ unsigned long long clock:52;
+ unsigned long long exception:1;
+ unsigned long long level:3;
+ unsigned long long cpuid:8;
+ } fields;
+
+ 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; */
+
+
+static unsigned int dbf_version;
+
+/* struct is used to manage contents of structs debug_info from dump
+ * in lcrash
+ */
+typedef struct debug_info_s {
+ struct debug_info_s *next;
+ struct debug_info_s *prev;
+ kaddr_t next_dbi; /* store next ptr of struct in dump */
+ kaddr_t prev_dbi; /* store prev ptr of struct in dump */
+ int level;
+ int nr_areas;
+ int page_order;
+ int buf_size;
+ int entry_size;
+ void **areas; /* contents of debug areas from dump */
+ int active_area;
+ int *active_entry; /* change to uint32_t ? */
+ debug_view_t *views[DEBUG_MAX_VIEWS];
+ char name[DEBUG_MAX_PROCF_LEN];
+ kaddr_t addr;
+ int pages_per_area_v2;
+ void ***areas_v2;
+} debug_info_t;
+
+
+/* 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,
+ char* out_buf);
+typedef int (debug_format_proc_t) (debug_info_t* id, debug_view_t* view,
+ char* out_buf, const char* in_buf);
+typedef int (debug_prolog_proc_t) (debug_info_t* id, debug_view_t* view,
+ char* out_buf);
+
+struct debug_view_s {
+ char name[DEBUG_MAX_PROCF_LEN];
+ debug_prolog_proc_t* prolog_proc;
+ debug_header_proc_t* header_proc;
+ debug_format_proc_t* format_proc;
+ void* private_data;
+};
+
+#define LCRASH_DB_VIEWS 1000
+
+static debug_info_t *debug_area_first = NULL;
+static debug_info_t *debug_area_last = NULL;
+static debug_view_t *debug_views[LCRASH_DB_VIEWS];
+static int initialized = 0;
+static iconv_t ebcdic_ascii_conv = 0;
+
+void s390dbf_usage(command_t * cmd);
+static int add_lcrash_debug_view(debug_view_t *);
+static int dbe_size = 0;
+
+static void
+EBCASC(char *inout, size_t len)
+{
+ iconv(ebcdic_ascii_conv, &inout, &len, &inout, &len);
+}
+
+/*
+ * prints header for debug entry
+ */
+static int
+dflt_header_fn(debug_info_t * id, debug_view_t *view,
+ int area, debug_entry_t * entry, char *out_buf)
+{
+ struct timeval time_val;
+ unsigned long long time;
+ char *except_str;
+ kaddr_t caller;
+ int rc = 0;
+ char *caller_name;
+ 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);
+
+ if (lentry.id.fields.exception)
+ except_str = "*";
+ else
+ except_str = "-";
+ caller = lentry.caller;
+ if(KL_ARCH == KL_ARCH_S390){
+ caller &= 0x7fffffff;
+ }
+ caller_sym = kl_lkup_symaddr(caller);
+ if(caller_sym){
+ caller_name = caller_sym->s_name;
+ offset = caller - kl_funcaddr(caller);
+ }
+ else {
+ sprintf(caller_buf, "%"FMTPTR"x", caller);
+ caller_name = caller_buf;
+ offset = 0;
+ }
+
+ 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;
+}
+
+/*
+ * prints debug header in raw format
+ */
+static int
+raw_header_fn(debug_info_t * id, debug_view_t *view,
+ int area, debug_entry_t * entry, char *out_buf)
+{
+ int rc;
+
+ rc = sizeof(debug_entry_t);
+ if (out_buf == NULL)
+ goto out;
+ memcpy(out_buf,entry,sizeof(debug_entry_t));
+ out:
+ return rc;
+}
+
+/*
+ * prints debug data in raw format
+ */
+static int
+raw_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+ int rc;
+
+ rc = id->buf_size;
+ if (out_buf == NULL || in_buf == NULL)
+ goto out;
+ memcpy(out_buf, in_buf, id->buf_size);
+ out:
+ return rc;
+}
+
+/*
+ * prints debug data in hex/ascii format
+ */
+static int
+hex_ascii_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+ int i, rc = 0;
+
+ if (out_buf == NULL || in_buf == NULL) {
+ rc = id->buf_size * 4 + 3;
+ goto out;
+ }
+ for (i = 0; i < id->buf_size; i++) {
+ rc += sprintf(out_buf + rc, "%02x ",
+ ((unsigned char *) in_buf)[i]);
+ }
+ rc += sprintf(out_buf + rc, "| ");
+ for (i = 0; i < id->buf_size; i++) {
+ unsigned char c = in_buf[i];
+ if (!isprint(c))
+ rc += sprintf(out_buf + rc, ".");
+ else
+ rc += sprintf(out_buf + rc, "%c", c);
+ }
+ rc += sprintf(out_buf + rc, "\n");
+ out:
+ return rc;
+}
+
+/*
+ * prints debug data in sprintf format
+ */
+static int
+sprintf_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+#define _BUFSIZE 1024
+ char buf[_BUFSIZE];
+ int i, k, rc = 0, num_longs = 0, num_used_args = 0, num_strings = 0;
+ /* use kaddr_t to store long values of 32bit and 64bit archs here */
+ kaddr_t inbuf_cpy[DEBUG_SPRINTF_MAX_ARGS];
+ /* store ptrs to strings to be deallocated at end of this function */
+ uaddr_t to_dealloc[DEBUG_SPRINTF_MAX_ARGS];
+ kaddr_t addr;
+
+ memset(buf, 0, sizeof(buf));
+ memset(inbuf_cpy, 0, sizeof(inbuf_cpy));
+ memset(to_dealloc, 0, sizeof(to_dealloc));
+
+ if (out_buf == NULL || in_buf == NULL) {
+ rc = id->buf_size * 4 + 3;
+ goto out;
+ }
+
+ /* get the format string into buf */
+ addr = KL_GET_PTR((void*)in_buf);
+ GET_BLOCK(addr, _BUFSIZE, buf);
+
+ k = 0;
+ for (i = 0; buf[i] && (buf[i] != '\n'); i++) {
+ if (buf[i] != '%')
+ continue;
+ if (k == DEBUG_SPRINTF_MAX_ARGS) {
+ fprintf(KL_ERRORFP,
+ "\nToo much parameters in sprinf view (%i)\n"
+ ,k + 1);
+ fprintf(KL_ERRORFP, "Format String: %s)\n", buf);
+ break;
+ }
+ /* for sprintf we have only unsigned long values ... */
+ if (buf[i+1] != 's'){
+ /* we use KL_GET_PTR here to read ulong value */
+ addr = KL_GET_PTR((void*) in_buf + ((k + 1)* KL_NBPW));
+ inbuf_cpy[k] = addr;
+ } else { /* ... or ptrs to strings in debug areas */
+ inbuf_cpy[k] = (uaddr_t) malloc(_BUFSIZE);
+ to_dealloc[num_strings++] = inbuf_cpy[k];
+ addr = KL_GET_PTR((void*) in_buf + ((k + 1)* KL_NBPW));
+ GET_BLOCK(addr, _BUFSIZE,
+ (void*)(uaddr_t)(inbuf_cpy[k]));
+ }
+ k++;
+ }
+
+ /* count of longs fit into one entry */
+ num_longs = id->buf_size / KL_NBPW; /* sizeof(long); */
+ if(num_longs < 1) /* bufsize of entry too small */
+ goto out;
+ if(num_longs == 1) { /* no args, just print the format string */
+ rc = sprintf(out_buf + rc, "%s", buf);
+ goto out;
+ }
+
+ /* number of arguments used for sprintf (without the format string) */
+ num_used_args = MIN(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
+
+ rc = sprintf(out_buf + rc, buf, (uaddr_t)(inbuf_cpy[0]),
+ (uaddr_t)(inbuf_cpy[1]), (uaddr_t)(inbuf_cpy[2]),
+ (uaddr_t)(inbuf_cpy[3]), (uaddr_t)(inbuf_cpy[4]),
+ (uaddr_t)(inbuf_cpy[5]), (uaddr_t)(inbuf_cpy[6]),
+ (uaddr_t)(inbuf_cpy[7]), (uaddr_t)(inbuf_cpy[8]),
+ (uaddr_t)(inbuf_cpy[9]));
+ out:
+ while (num_strings--){
+ free((char*)(to_dealloc[num_strings]));
+ }
+ return rc;
+}
+
+
+/***********************************
+ * functions for debug-views
+ ***********************************/
+
+/*
+ * prints out actual debug level
+ */
+static int
+prolog_level_fn(debug_info_t * id,
+ debug_view_t *view, char *out_buf)
+{
+ int rc = 0;
+
+ if (out_buf == NULL) {
+ rc = 2;
+ goto out;
+ }
+ rc = sprintf(out_buf, "%i\n", id->level);
+ out:
+ return rc;
+}
+
+/*
+ * prints out actual pages_per_area
+ */
+static int
+prolog_pages_fn(debug_info_t * id,
+ debug_view_t *view, char *out_buf)
+{
+ int rc = 0;
+
+ if (out_buf == NULL) {
+ rc = 2;
+ goto out;
+ }
+ rc = sprintf(out_buf, "%i\n", id->pages_per_area_v2);
+ out:
+ return rc;
+}
+
+/*
+ * prints out prolog
+ */
+static int
+prolog_fn(debug_info_t * id,
+ debug_view_t *view, char *out_buf)
+{
+ int rc = 0;
+
+ rc = sprintf(out_buf, "AREA TIME LEVEL EXCEPTION CP CALLING FUNCTION"
+ " + OFFSET DATA\n==================================="
+ "=======================================\n");
+ return rc;
+}
+
+/*
+ * prints debug data in hex format
+ */
+static int
+hex_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+ int i, rc = 0;
+
+ for (i = 0; i < id->buf_size; i++) {
+ rc += sprintf(out_buf + rc, "%02x ",
+ ((unsigned char *) in_buf)[i]);
+ }
+ rc += sprintf(out_buf + rc, "\n");
+ return rc;
+}
+
+/*
+ * prints debug data in ascii format
+ */
+static int
+ascii_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+ int i, rc = 0;
+
+ if (out_buf == NULL || in_buf == NULL) {
+ rc = id->buf_size + 1;
+ goto out;
+ }
+ for (i = 0; i < id->buf_size; i++) {
+ unsigned char c = in_buf[i];
+ if (!isprint(c))
+ rc += sprintf(out_buf + rc, ".");
+ else
+ rc += sprintf(out_buf + rc, "%c", c);
+ }
+ rc += sprintf(out_buf + rc, "\n");
+ out:
+ return rc;
+}
+
+/*
+ * prints debug data in ebcdic format
+ */
+static int
+ebcdic_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+ int i, rc = 0;
+
+ if (out_buf == NULL || in_buf == NULL) {
+ rc = id->buf_size + 1;
+ goto out;
+ }
+ for (i = 0; i < id->buf_size; i++) {
+ char c = in_buf[i];
+ EBCASC(&c, 1);
+ if (!isprint(c))
+ rc += sprintf(out_buf + rc, ".");
+ else
+ rc += sprintf(out_buf + rc, "%c", c);
+ }
+ rc += sprintf(out_buf + rc, "\n");
+ out:
+ return rc;
+}
+
+debug_view_t ascii_view = {
+ "ascii",
+ &prolog_fn,
+ &dflt_header_fn,
+ &ascii_format_fn,
+};
+
+debug_view_t ebcdic_view = {
+ "ebcdic",
+ &prolog_fn,
+ &dflt_header_fn,
+ &ebcdic_format_fn,
+};
+
+debug_view_t hex_view = {
+ "hex",
+ &prolog_fn,
+ &dflt_header_fn,
+ &hex_format_fn,
+};
+
+debug_view_t level_view = {
+ "level",
+ &prolog_level_fn,
+ NULL,
+ NULL,
+};
+
+debug_view_t pages_view = {
+ "pages",
+ &prolog_pages_fn,
+ NULL,
+ NULL,
+};
+
+debug_view_t raw_view = {
+ "raw",
+ NULL,
+ &raw_header_fn,
+ &raw_format_fn,
+};
+
+debug_view_t hex_ascii_view = {
+ "hex_ascii",
+ &prolog_fn,
+ &dflt_header_fn,
+ &hex_ascii_format_fn,
+};
+
+debug_view_t sprintf_view = {
+ "sprintf",
+ &prolog_fn,
+ &dflt_header_fn,
+ &sprintf_format_fn,
+};
+
+
+static debug_entry_t *
+debug_find_oldest_entry(debug_entry_t *entries, int num, int entry_size)
+{
+ debug_entry_t *result, *current;
+ int i;
+ uint64_t clock1, clock2;
+
+ result = entries;
+ current = entries;
+ for (i=0; i < num; i++) {
+ if (current->id.stck == 0)
+ break;
+ clock1 = current->id.fields.clock;
+ clock2 = result->id.fields.clock;
+ clock1 = KL_GET_UINT64(&clock1);
+ clock2 = KL_GET_UINT64(&clock2);
+ if (clock1 < clock2)
+ result = current;
+ current = (debug_entry_t *) ((char *) current + entry_size);
+ }
+ return result;
+}
+
+
+/*
+ * debug_format_output:
+ * - calls prolog, header and format functions of view to format output
+ */
+static int
+debug_format_output_v1(debug_info_t * debug_area, debug_view_t *view,
+ FILE * ofp)
+{
+ int i, j, len;
+ int nr_of_entries;
+ debug_entry_t *act_entry, *last_entry;
+ char *act_entry_data;
+ char buf[2048];
+
+ /* print prolog */
+ if (view->prolog_proc) {
+ len = view->prolog_proc(debug_area, view, buf);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ /* print debug records */
+ if (!(view->format_proc) && !(view->header_proc))
+ goto out;
+ if(debug_area->entry_size <= 0){
+ fprintf(ofp, "Invalid entry_size: %i\n",debug_area->entry_size);
+ goto out;
+ }
+ nr_of_entries = (PAGE_SIZE << debug_area->page_order) / debug_area->entry_size;
+ for (i = 0; i < debug_area->nr_areas; i++) {
+ 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] +
+ (PAGE_SIZE << debug_area->page_order) -
+ debug_area->entry_size);
+ for (j = 0; j < nr_of_entries; j++) {
+ act_entry_data = (char*)act_entry + dbe_size;
+ if (act_entry->id.stck == 0)
+ break; /* empty entry */
+ if (view->header_proc) {
+ len = view->header_proc(debug_area, view, i,
+ act_entry, buf);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ if (view->format_proc) {
+ len = view->format_proc(debug_area, view,
+ buf, act_entry_data);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ act_entry =
+ (debug_entry_t *) (((char *) act_entry) +
+ debug_area->entry_size);
+ if (act_entry > last_entry)
+ act_entry = debug_area->areas[i];
+ }
+ }
+ out:
+ return 1;
+}
+
+/*
+ * debug_format_output_v2:
+ * - calls prolog, header and format functions of view to format output
+ */
+static int
+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;
+ char *act_entry_data;
+ char buf[2048];
+
+ /* print prolog */
+ if (view->prolog_proc) {
+ len = view->prolog_proc(debug_area, view, buf);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ /* print debug records */
+ if (!(view->format_proc) && !(view->header_proc))
+ goto out;
+ if(debug_area->entry_size <= 0){
+ fprintf(ofp, "Invalid entry_size: %i\n",debug_area->entry_size);
+ goto out;
+ }
+ for (i = 0; i < debug_area->nr_areas; i++) {
+ int nr_entries_per_page = PAGE_SIZE/debug_area->entry_size;
+ for (j = 0; j < debug_area->pages_per_area_v2; j++) {
+ 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)
+ break; /* empty entry */
+ if (view->header_proc) {
+ len = view->header_proc(debug_area,
+ view, i, act_entry, buf);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ if (view->format_proc) {
+ len = view->format_proc(debug_area,
+ view, buf, act_entry_data);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ act_entry = (debug_entry_t *) (((char *)
+ act_entry) + debug_area->entry_size);
+ }
+ }
+ }
+out:
+ return 1;
+}
+
+static debug_info_t *
+find_debug_area(const char *area_name)
+{
+ debug_info_t* act_debug_info = debug_area_first;
+ while(act_debug_info != NULL){
+ if (strcmp(act_debug_info->name, area_name) == 0)
+ return act_debug_info;
+ act_debug_info = act_debug_info->next;
+ }
+ return NULL;
+}
+
+static void
+dbf_init(void)
+{
+ if (!initialized) {
+ if(dbf_version >= DBF_VERSION_V2)
+ add_lcrash_debug_view(&pages_view);
+ add_lcrash_debug_view(&ascii_view);
+ add_lcrash_debug_view(&level_view);
+ add_lcrash_debug_view(&ebcdic_view);
+ add_lcrash_debug_view(&hex_view);
+ add_lcrash_debug_view(&hex_ascii_view);
+ add_lcrash_debug_view(&sprintf_view);
+ add_lcrash_debug_view(&raw_view);
+ ebcdic_ascii_conv = iconv_open("ISO-8859-1", "EBCDIC-US");
+ initialized = 1;
+ }
+}
+
+static debug_view_t*
+get_debug_view(kaddr_t addr)
+{
+ void* k_debug_view;
+ int k_debug_view_size;
+ debug_view_t* rc;
+
+ rc = (debug_view_t*)malloc(sizeof(debug_view_t));
+ memset(rc, 0, sizeof(debug_view_t));
+
+ k_debug_view_size = kl_struct_len("debug_view");
+ k_debug_view = malloc(k_debug_view_size);
+ GET_BLOCK(addr, k_debug_view_size, k_debug_view);
+ strncpy(rc->name,K_PTR(k_debug_view,"debug_view","name"),
+ DEBUG_MAX_PROCF_LEN);
+
+ free(k_debug_view);
+ return rc;
+}
+
+static void
+free_debug_view(debug_view_t* view)
+{
+ if(view)
+ free(view);
+}
+
+static void
+debug_get_areas_v1(debug_info_t* db_info, void* k_dbi)
+{
+ kaddr_t mem_pos;
+ kaddr_t dbe_addr;
+ int area_size, i;
+
+ /* get areas */
+ /* place to hold ptrs to debug areas in lcrash */
+ area_size = PAGE_SIZE << db_info->page_order;
+ db_info->areas = (void**)malloc(db_info->nr_areas * sizeof(void *));
+ memset(db_info->areas, 0, db_info->nr_areas * sizeof(void *));
+ mem_pos = (kaddr_t) KL_UINT(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);
+ /* read raw data for debug area */
+ GET_BLOCK(dbe_addr, area_size, db_info->areas[i]);
+ mem_pos += KL_NBPW;
+ }
+}
+
+static void
+debug_get_areas_v2(debug_info_t* db_info, void* k_dbi)
+{
+ kaddr_t area_ptr;
+ kaddr_t page_array_ptr;
+ kaddr_t page_ptr;
+ int i,j;
+ db_info->areas_v2=(void***)malloc(db_info->nr_areas * sizeof(void **));
+ area_ptr = (kaddr_t) KL_UINT(k_dbi,"debug_info","areas");
+ for (i = 0; i < db_info->nr_areas; i++) {
+ db_info->areas_v2[i] = (void**)malloc(db_info->pages_per_area_v2
+ * sizeof(void*));
+ page_array_ptr = KL_VREAD_PTR(area_ptr);
+ for(j=0; j < db_info->pages_per_area_v2; j++) {
+ page_ptr = KL_VREAD_PTR(page_array_ptr);
+ db_info->areas_v2[i][j] = (void*)malloc(PAGE_SIZE);
+ /* read raw data for debug area */
+ GET_BLOCK(page_ptr, PAGE_SIZE, db_info->areas_v2[i][j]);
+ page_array_ptr += KL_NBPW;
+ }
+ area_ptr += KL_NBPW;
+ }
+}
+
+static debug_info_t*
+get_debug_info(kaddr_t addr,int get_areas)
+{
+ void *k_dbi;
+ kaddr_t mem_pos;
+ kaddr_t view_addr;
+ debug_info_t* db_info;
+ int i;
+ int dbi_size;
+
+ /* get sizes of kernel structures */
+ if(!(dbi_size = kl_struct_len("debug_info"))){
+ fprintf (KL_ERRORFP,
+ "Could not determine sizeof(struct debug_info)\n");
+ return(NULL);
+ }
+ if(!(dbe_size = kl_struct_len("__debug_entry"))){
+ fprintf(KL_ERRORFP,
+ "Could not determine sizeof(struct __debug_entry)\n");
+ return(NULL);
+ }
+
+ /* get kernel debug_info structure */
+ k_dbi = malloc(dbi_size);
+ GET_BLOCK(addr, dbi_size, k_dbi);
+
+ db_info = (debug_info_t*)malloc(sizeof(debug_info_t));
+ memset(db_info, 0, sizeof(debug_info_t));
+
+ /* copy members */
+ db_info->level = KL_INT(k_dbi,"debug_info","level");
+ db_info->nr_areas = KL_INT(k_dbi,"debug_info","nr_areas");
+ db_info->pages_per_area_v2= KL_INT(k_dbi,"debug_info","pages_per_area");
+ db_info->page_order = KL_INT(k_dbi,"debug_info","page_order");
+ db_info->buf_size = KL_INT(k_dbi,"debug_info","buf_size");
+ db_info->entry_size = KL_INT(k_dbi,"debug_info","entry_size");
+ db_info->next_dbi = KL_UINT(k_dbi,"debug_info","next");
+ db_info->prev_dbi = KL_UINT(k_dbi,"debug_info","prev");
+ db_info->addr = addr;
+ strncpy(db_info->name,K_PTR(k_dbi,"debug_info","name"),
+ DEBUG_MAX_PROCF_LEN);
+
+
+ if(get_areas){
+ if(dbf_version == DBF_VERSION_V1)
+ debug_get_areas_v1(db_info,k_dbi);
+ else
+ debug_get_areas_v2(db_info,k_dbi);
+ } else {
+ db_info->areas = NULL;
+ }
+
+ /* get views */
+ mem_pos = (uaddr_t) K_PTR(k_dbi,"debug_info","views");
+ memset(&db_info->views, 0, DEBUG_MAX_VIEWS * sizeof(void*));
+ for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+ view_addr = KL_GET_PTR((void*)(uaddr_t)mem_pos);
+ if(view_addr == 0){
+ break;
+ } else {
+ db_info->views[i] = get_debug_view(view_addr);
+ }
+ mem_pos += KL_NBPW;
+ }
+ free(k_dbi);
+ return db_info;
+}
+
+static void
+free_debug_info_v1(debug_info_t * db_info)
+{
+ int i;
+ if(db_info->areas){
+ for (i = 0; i < db_info->nr_areas; i++) {
+ free(db_info->areas[i]);
+ }
+ }
+ for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+ free_debug_view(db_info->views[i]);
+ }
+ free(db_info->areas);
+ free(db_info);
+}
+
+static void
+free_debug_info_v2(debug_info_t * db_info)
+{
+ int i,j;
+ if(db_info->areas) {
+ for (i = 0; i < db_info->nr_areas; i++) {
+ for(j = 0; j < db_info->pages_per_area_v2; j++) {
+ free(db_info->areas_v2[i][j]);
+ }
+ free(db_info->areas[i]);
+ }
+ free(db_info->areas);
+ db_info->areas = NULL;
+ }
+ for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+ free_debug_view(db_info->views[i]);
+ }
+ free(db_info);
+}
+
+static int
+get_debug_areas(void)
+{
+ kaddr_t act_debug_area;
+ syment_t *debug_sym;
+ debug_info_t *act_debug_area_cpy;
+
+ if(!(debug_sym = kl_lkup_symname("debug_area_first"))){
+ printf("Did not find debug_areas");
+ return -1;
+ }
+ act_debug_area = KL_VREAD_PTR(debug_sym->s_addr);
+ while(act_debug_area != 0){
+ act_debug_area_cpy = get_debug_info(act_debug_area,0);
+ act_debug_area = act_debug_area_cpy->next_dbi;
+ if(debug_area_first == NULL){
+ debug_area_first = act_debug_area_cpy;
+ } else {
+ debug_area_last->next = act_debug_area_cpy;
+ }
+ debug_area_last = act_debug_area_cpy;
+ }
+ return 0;
+}
+
+static void
+free_debug_areas(void)
+{
+ debug_info_t* next;
+ debug_info_t* act_debug_info = debug_area_first;
+
+ while(act_debug_info != NULL){
+ next = act_debug_info->next;
+ if(dbf_version == DBF_VERSION_V1)
+ free_debug_info_v1(act_debug_info);
+ else
+ free_debug_info_v2(act_debug_info);
+ act_debug_info = next;
+ }
+
+ debug_area_first = NULL;
+ debug_area_last = NULL;
+}
+
+static debug_view_t *
+find_lcrash_debug_view(const char *name)
+{
+ int i;
+ for (i = 0; (i < LCRASH_DB_VIEWS) && (debug_views[i] != NULL); i++) {
+ if (strcmp(debug_views[i]->name, name) == 0)
+ return debug_views[i];
+ }
+ return NULL;
+}
+
+static void
+print_lcrash_debug_views(FILE * ofp)
+{
+ int i;
+ fprintf(ofp, "REGISTERED VIEWS\n");
+ fprintf(ofp, "=====================\n");
+ for (i = 0; i < LCRASH_DB_VIEWS; i++) {
+ if (debug_views[i] == NULL) {
+ return;
+ }
+ fprintf(ofp, " - %s\n", debug_views[i]->name);
+ }
+}
+
+static int
+add_lcrash_debug_view(debug_view_t *view)
+{
+ int i;
+ for (i = 0; i < LCRASH_DB_VIEWS; i++) {
+ if (debug_views[i] == NULL) {
+ debug_views[i] = view;
+ return 0;
+ }
+ if (strcmp(debug_views[i]->name, view->name) == 0)
+ return -1;
+ }
+ return -1;
+}
+
+static int
+list_one_view(char *area_name, char *view_name, command_t * cmd)
+{
+ debug_info_t *db_info;
+ debug_view_t *db_view;
+
+ if ((db_info = find_debug_area(area_name)) == NULL) {
+ fprintf(cmd->efp, "Debug log '%s' not found!\n", area_name);
+ return -1;
+ }
+
+ db_info = get_debug_info(db_info->addr,1);
+
+ if ((db_view = find_lcrash_debug_view(view_name)) == NULL) {
+ fprintf(cmd->efp, "View '%s' not registered!\n", view_name);
+ return -1;
+ }
+ if(dbf_version == DBF_VERSION_V1){
+ debug_format_output_v1(db_info, db_view, cmd->ofp);
+ free_debug_info_v1(db_info);
+ } else {
+ debug_format_output_v2(db_info, db_view, cmd->ofp);
+ free_debug_info_v2(db_info);
+ }
+ return 0;
+}
+
+static int
+list_areas(FILE * ofp)
+{
+ debug_info_t* act_debug_info = debug_area_first;
+ fprintf(ofp, "Debug Logs:\n");
+ fprintf(ofp, "==================\n");
+ while(act_debug_info != NULL){
+ fprintf(ofp, " - %s\n", act_debug_info->name);
+ act_debug_info = act_debug_info->next;
+ }
+ return 0;
+}
+
+static int
+list_one_area(const char *area_name, command_t * cmd)
+{
+ debug_info_t *db_info;
+ int i;
+ if ((db_info = find_debug_area(area_name)) == NULL) {
+ fprintf(cmd->efp, "Debug log '%s' not found!\n", area_name);
+ return -1;
+ }
+ fprintf(cmd->ofp, "INSTALLED VIEWS FOR '%s':\n", area_name);
+ fprintf(cmd->ofp, "================================================"
+ "==============================\n");
+ for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+ if (db_info->views[i] != NULL) {
+ fprintf(cmd->ofp, " - %s ", db_info->views[i]->name);
+ if (find_lcrash_debug_view(db_info->views[i]->name))
+ fprintf(cmd->ofp, "(available)\n");
+ else
+ fprintf(cmd->ofp, "(not available)\n");
+ }
+ }
+ fprintf(cmd->ofp, "================================================="
+ "=============================\n");
+ return 0;
+}
+
+#ifdef DBF_DYNAMIC_VIEWS
+static int
+load_debug_view(const char *path, command_t * cmd)
+{
+ void *library;
+ const char *error;
+ debug_view_t *(*view_init_func) (void);
+
+ library = dlopen(path, RTLD_LAZY);
+ if (library == NULL) {
+ fprintf(cmd->efp, "Could not open %s: %s\n", path, dlerror());
+ return (1);
+ }
+
+ dlerror();
+
+ view_init_func = dlsym(library, "debug_view_init");
+ error = dlerror();
+
+ if (error) {
+ fprintf(stderr, "could not find debug_view_init(): %s\n",
+ error);
+ exit(1);
+ }
+
+ add_lcrash_debug_view((*view_init_func) ());
+
+ fprintf(cmd->ofp, "view %s loaded\n", path);
+ fflush(stdout);
+ return 0;
+}
+#endif
+
+/*
+ * s390dbf_cmd() -- Run the 's390dbf' command.
+ */
+static int
+s390dbf_cmd(command_t * cmd)
+{
+ syment_t *dbf_version_sym;
+ int rc = 0;
+
+ /* check version */
+
+ if(!(dbf_version_sym = kl_lkup_symname("debug_feature_version"))){
+ fprintf(KL_ERRORFP,
+ "Could not determine debug_feature_version\n");
+ return -1;
+ }
+
+ dbf_version = KL_VREAD_UINT32(dbf_version_sym->s_addr);
+
+ if ((dbf_version != DBF_VERSION_V1) && (dbf_version != DBF_VERSION_V2)){
+ 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);
+ return -1;
+ }
+
+ dbf_init();
+
+ if (cmd->flags & C_ALL) {
+ return (0);
+ }
+#ifdef DBF_DYNAMIC_VIEWS
+ if (cmd->flags & LOAD_FLAG) {
+ printf("loading: %s\n", cmd->args[0]);
+ return (load_debug_view(cmd->args[0], cmd));
+ }
+#endif
+ if (cmd->flags & VIEWS_FLAG) {
+ print_lcrash_debug_views(cmd->ofp);
+ return (0);
+ }
+ if (cmd->nargs > 2) {
+ s390dbf_usage(cmd);
+ return (1);
+ }
+
+ if(get_debug_areas() == -1)
+ return -1;
+
+ switch (cmd->nargs) {
+ case 0:
+ rc = list_areas(cmd->ofp);
+ break;
+ case 1:
+ rc = list_one_area(cmd->args[0], cmd);
+ break;
+ case 2:
+ rc = list_one_view(cmd->args[0], cmd->args[1], cmd);
+ break;
+ }
+
+ free_debug_areas();
+
+ return rc;
+}
+
+#define _S390DBF_USAGE " [-v] [debug log] [debug view]"
+
+/*
+ * s390dbf_usage() -- Print the usage string for the 's390dbf' command.
+ */
+void
+s390dbf_usage(command_t * cmd)
+{
+ CMD_USAGE(cmd, _S390DBF_USAGE);
+}
+
+/*
+ * s390 debug feature command for crash
+ */
+
+char *help_s390dbf[] = {
+ "s390dbf",
+ "s390dbf prints out debug feature logs",
+ "[-v] [debug_log] [debug_log view]",
+ "",
+ "Display Debug logs:",
+ " + If called without parameters, all active debug logs are listed.",
+ " + If called with '-v', all debug views which are available to",
+ " 'crash' are listed",
+ " + If called with the name of a debug log, all debug-views for which",
+ " the debug-log has registered are listed. It is possible thatsome",
+ " of the debug views are not available to 'crash'.",
+ " + If called with the name of a debug-log and an available viewname,",
+ " the specified view is printed.",
+ NULL
+};
+
+void cmd_s390dbf()
+{
+ int i,c;
+
+ command_t cmd = {
+ .ofp = stdout,
+ .efp = stderr,
+ .cmdstr = "s390dbf",
+ .command = "s390dbf",
+ };
+
+ cmd.nargs=argcnt - 1;
+ for (i=1; i < argcnt; i++)
+ cmd.args[i-1] = args[i];
+
+ while ((c = getopt(argcnt, args, "v")) != EOF) {
+ switch(c) {
+ case 'v':
+ cmd.flags |= VIEWS_FLAG;
+ break;
+ default:
+ s390dbf_usage(&cmd);
+ return;
+ }
+ }
+ s390dbf_cmd(&cmd);
+}
+
+#endif
18 years, 3 months
s390dbf support for crash
by Michael Holzheu
Hi Dave,
For lcrash we have a command, to print out kernel traces from
the s390 debug feature (s390dbf). The debug feature is an s390 kernel
trace API which uses wraparound buffers to store trace records in memory.
Many of the s390 device drivers use this feature. Since more and more
service and support people use crash instead of lcrash for dump
analysis, it would be very useful to have this command in the crash
dumpanalysis tool, too. There is some documentation of the s390dbf in
the kernel sources under /Documentation/s390/s390dbf.txt
Here are some examples, how the command works:
1. Display all registerd debug features:
----------------------------------------
crash> s390dbf
Debug Logs:
==================
- cio_msg
- cio_crw
- qdio_setup
...
2. Show content of a debug feature:
-----------------------------------
crash> s390dbf cio_msg sprintf
00 01155560919:434118 2 - 02 <ccw_device_sense_id_irq+0320>
SenseID : UC on dev 0.0.e89e, lpum 80, cnt 00, sns : 10000000 9EFF003FF ...
00 01155560919:434273 2 - 02 <ccw_device_recog_done+0956>
SenseID : device 0.0.eee2 reports: CU Type/Mod = 3990/E9, Dev Type/Mod = 3390/0A
00 01155560919:434291 2 - 02 <ccw_device_recog_done+0956>
SenseID : device 0.0.e919 reports: CU Type/Mod = 3990/E9, Dev Type/Mod = 3390/0C
Would you please consider integrating the command into crash?
Here the patch against "crash-4.0-3.1":
---
Makefile | 11
defs.h | 6
global_data.c | 3
s390dbf.c | 1340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 1356 insertions(+), 4 deletions(-)
diff -Naur crash-4.0-3.1/Makefile crash-4.0-3.1-s390dbf/Makefile
--- crash-4.0-3.1/Makefile 2006-08-04 17:24:00.000000000 +0200
+++ crash-4.0-3.1-s390dbf/Makefile 2006-08-14 15:57:29.000000000 +0200
@@ -73,7 +73,7 @@
CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \
kernel.c test.c gdb_interface.c configure.c net.c dev.c \
- alpha.c x86.c ppc.c ia64.c s390.c s390x.c ppc64.c x86_64.c \
+ alpha.c x86.c ppc.c ia64.c s390.c s390x.c s390dbf.c ppc64.c x86_64.c \
extensions.c remote.c va_server.c va_server_v1.c symbols.c cmdline.c \
lkcd_common.c lkcd_v1.c lkcd_v2_v3.c lkcd_v5.c lkcd_v7.c lkcd_v8.c\
lkcd_fix_mem.c s390_dump.c lkcd_x86_trace.c \
@@ -85,7 +85,7 @@
OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \
build_data.o kernel.o test.o gdb_interface.o net.o dev.o \
- alpha.o x86.o ppc.o ia64.o s390.o s390x.o ppc64.o x86_64.o \
+ alpha.o x86.o ppc.o ia64.o s390.o s390x.o s390dbf.o ppc64.o x86_64.o \
extensions.o remote.o va_server.o va_server_v1.o symbols.o cmdline.o \
lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \
lkcd_fix_mem.o s390_dump.o netdump.o diskdump.o xendump.o \
@@ -364,6 +364,9 @@
s390x.o: ${GENERIC_HFILES} ${IBM_HFILES} s390x.c
cc -c ${CFLAGS} s390x.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+s390dbf.o: ${GENERIC_HFILES} ${IBM_HFILES} s390dbf.c
+ cc -c ${CFLAGS} s390dbf.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+
s390_dump.o: ${GENERIC_HFILES} ${IBM_HFILES} s390_dump.c
cc -c ${CFLAGS} s390_dump.c ${WARNING_OPTIONS} ${WARNING_ERROR}
diff -Naur crash-4.0-3.1/defs.h crash-4.0-3.1-s390dbf/defs.h
--- crash-4.0-3.1/defs.h 2006-08-04 17:24:00.000000000 +0200
+++ crash-4.0-3.1-s390dbf/defs.h 2006-08-14 15:57:24.000000000 +0200
@@ -2822,6 +2822,9 @@
void cmd_gdb(void); /* gdb_interface.c */
void cmd_net(void); /* net.c */
void cmd_extend(void); /* extensions.c */
+#if defined(S390) || defined(S390X)
+void cmd_s390dbf(void);
+#endif
/*
* main.c
@@ -3239,6 +3242,9 @@
extern char *help_waitq[];
extern char *help_whatis[];
extern char *help_wr[];
+#if defined(S390) || defined(S390X)
+extern char *help_s390dbf[];
+#endif
/*
* task.c
diff -Naur crash-4.0-3.1/global_data.c crash-4.0-3.1-s390dbf/global_data.c
--- crash-4.0-3.1/global_data.c 2006-08-04 17:24:00.000000000 +0200
+++ crash-4.0-3.1-s390dbf/global_data.c 2006-08-14 15:57:34.000000000 +0200
@@ -117,6 +117,9 @@
{"waitq", cmd_waitq, help_waitq, REFRESH_TASK_TABLE},
{"whatis", cmd_whatis, help_whatis, 0},
{"wr", cmd_wr, help_wr, 0},
+#if defined(S390) || defined(S390X)
+ {"s390dbf", cmd_s390dbf, help_s390dbf, 0},
+#endif
{(char *)NULL}
};
diff -Naur crash-4.0-3.1/s390dbf.c crash-4.0-3.1-s390dbf/s390dbf.c
--- crash-4.0-3.1/s390dbf.c 1970-01-01 01:00:00.000000000 +0100
+++ crash-4.0-3.1-s390dbf/s390dbf.c 2006-08-14 15:57:17.000000000 +0200
@@ -0,0 +1,1340 @@
+/*
+ * s390 debug feature command for crash
+ *
+ * Copyright (C) IBM Corp. 2006
+ * Author(s): Michael Holzheu <holzheu(a)de.ibm.com>
+ */
+
+#if defined(S390) || defined(S390X)
+
+#include "defs.h"
+#include <iconv.h>
+#include <ctype.h>
+
+/*
+ * Compat layer to integrate lcrash commands into crash
+ * Maps lcrash API to crash functions
+ */
+
+#define KL_NBPW sizeof(long)
+#define KL_ERRORFP stderr
+#define MAX_ARGS 128
+#define MAX_CMDLINE 256
+
+#define C_FALSE 0x00000001 /* Command takes no arguments */
+#define C_TRUE 0x00000002 /* Command requires arguments */
+#define C_ALL 0x00000004 /* All elements */
+#define C_PERM 0x00000008 /* Allocate perminant blocks */
+#define C_TEMP 0x00000000 /* For completeness */
+#define C_FULL 0x00000010 /* Full output */
+#define C_LIST 0x00000020 /* List items */
+#define C_NEXT 0x00000040 /* Follow links */
+#define C_WRITE 0x00000080 /* Write output to file */
+#define C_NO_OPCHECK 0x00000100 /* Don't reject bad cmd line options */
+#define C_ITER 0x00000200 /* set iteration threshold */
+
+#define C_LFLG_SHFT 12
+
+#define KL_ARCH_S390 0
+#define KL_ARCH_S390X 1
+#ifdef __s390x__
+#define KL_ARCH KL_ARCH_S390X
+#define FMTPTR "l"
+#define KL_PTRSZ 8
+#else
+#define KL_ARCH KL_ARCH_S390
+#define FMTPTR "ll"
+#define KL_PTRSZ 4
+#endif
+
+typedef unsigned long uaddr_t;
+typedef unsigned long kaddr_t;
+
+typedef struct _syment {
+ char *s_name;
+ kaddr_t s_addr;
+} syment_t;
+
+typedef struct option_s {
+ struct option_s *op_next;
+ char op_char;
+ char *op_arg;
+} option_t;
+
+typedef struct command_s {
+ int flags;
+ char cmdstr[MAX_CMDLINE];
+ char *command;
+ char *cmdline;
+ option_t *options;
+ int nargs;
+ char *args[MAX_ARGS];
+ char *pipe_cmd;
+ FILE *ofp;
+ FILE *efp;
+} command_t;
+
+static inline syment_t* kl_lkup_symaddr(kaddr_t addr)
+{
+ static syment_t sym;
+ struct syment *crash_sym;
+
+ crash_sym = value_search(addr, &sym.s_addr);
+ if (!crash_sym)
+ return NULL;
+ sym.s_name = crash_sym->name;
+ return &sym;
+}
+
+static inline syment_t* kl_lkup_symname(char* name)
+{
+ static syment_t sym;
+ kaddr_t addr;
+ sym.s_addr = symbol_value(name);
+ sym.s_name = NULL;
+ if(!sym.s_addr)
+ return NULL;
+ else
+ return &sym;
+}
+
+static inline void GET_BLOCK(kaddr_t addr, int size, void* ptr)
+{
+ readmem(addr, KVADDR,ptr,size,"GET_BLOCK",FAULT_ON_ERROR);
+}
+
+static inline kaddr_t KL_VREAD_PTR(kaddr_t addr)
+{
+ unsigned long ptr;
+ readmem(addr, KVADDR,&ptr,sizeof(ptr),"GET_BLOCK",FAULT_ON_ERROR);
+ return (kaddr_t)ptr;
+}
+
+static inline uint32_t KL_GET_UINT32(void* ptr)
+{
+ return *((uint32_t*)ptr);
+}
+
+static inline uint64_t KL_GET_UINT64(void* ptr)
+{
+ return *((uint64_t*)ptr);
+}
+
+static inline kaddr_t KL_GET_PTR(void* ptr)
+{
+ return *((kaddr_t*)ptr);
+}
+
+static inline void* K_PTR(void* addr, char* struct_name, char* member_name)
+{
+ return addr+MEMBER_OFFSET(struct_name,member_name);
+}
+
+static inline uint32_t KL_UINT(void* ptr, char* struct_name, char* member_name)
+{
+ return (uint32_t) ULONG(ptr+MEMBER_OFFSET(struct_name,member_name));
+}
+
+static inline uint32_t KL_VREAD_UINT32(kaddr_t addr)
+{
+ uint32_t rc;
+ readmem(addr, KVADDR,&rc,sizeof(rc),"KL_VREAD_UINT32",FAULT_ON_ERROR);
+ return rc;
+}
+
+static inline uint32_t KL_INT(void* ptr, char* struct_name, char* member_name)
+{
+ return UINT(ptr+MEMBER_OFFSET(struct_name,member_name));
+}
+
+static inline int set_cmd_flags(command_t *cmd, int flags, char *extraops)
+{
+ return 0;
+}
+
+static inline void kl_s390tod_to_timeval(uint64_t todval, struct timeval *xtime)
+{
+ todval -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
+
+ todval >>= 12;
+ xtime->tv_sec = todval / 1000000;
+ xtime->tv_usec = todval % 1000000;
+}
+
+static inline int kl_struct_len(char* struct_name)
+{
+ return STRUCT_SIZE(struct_name);
+}
+
+static inline kaddr_t kl_funcaddr(kaddr_t addr)
+{
+ struct syment *crash_sym;
+
+ crash_sym = value_search(addr, &addr);
+ if (!crash_sym)
+ return -1;
+ else
+ return crash_sym->value;
+}
+
+#define CMD_USAGE(cmd, s) \
+ fprintf(cmd->ofp, "Usage: %s %s\n", cmd->command, s); \
+ fprintf(cmd->ofp, "Enter \"help %s\" for details.\n",cmd->command);
+
+/*
+ * s390 debug feature implementation
+ */
+
+#ifdef DBF_DYNAMIC_VIEWS /* views defined in shared libs */
+#include <dlfcn.h>
+#endif
+
+/* Local flags
+ */
+
+#define LOAD_FLAG (1 << C_LFLG_SHFT)
+#define VIEWS_FLAG (2 << C_LFLG_SHFT)
+
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+/* Stuff which has to match with include/asm-s390/debug.h */
+
+#define DBF_VERSION_V1 1
+#define DBF_VERSION_V2 2
+#define PAGE_SIZE 4096
+#define DEBUG_MAX_VIEWS 10 /* max number of views in proc fs */
+#define DEBUG_MAX_PROCF_LEN 16 /* max length for a proc file name */
+#define DEBUG_SPRINTF_MAX_ARGS 10
+
+/* define debug-structures for lcrash */
+#define DEBUG_DATA(entry) (char*)(entry + 1)
+
+typedef struct debug_view_s debug_view_t;
+
+/* struct to hold contents of struct __debug_entry from dump
+ */
+typedef struct debug_entry_s{
+ union {
+ struct {
+ unsigned long long clock:52;
+ unsigned long long exception:1;
+ unsigned long long level:3;
+ unsigned long long cpuid:8;
+ } fields;
+
+ 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; */
+
+
+static unsigned int dbf_version;
+
+/* struct is used to manage contents of structs debug_info from dump
+ * in lcrash
+ */
+typedef struct debug_info_s {
+ struct debug_info_s *next;
+ struct debug_info_s *prev;
+ kaddr_t next_dbi; /* store next ptr of struct in dump */
+ kaddr_t prev_dbi; /* store prev ptr of struct in dump */
+ int level;
+ int nr_areas;
+ int page_order;
+ int buf_size;
+ int entry_size;
+ void **areas; /* contents of debug areas from dump */
+ int active_area;
+ int *active_entry; /* change to uint32_t ? */
+ debug_view_t *views[DEBUG_MAX_VIEWS];
+ char name[DEBUG_MAX_PROCF_LEN];
+ kaddr_t addr;
+ int pages_per_area_v2;
+ void ***areas_v2;
+} debug_info_t;
+
+
+/* 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,
+ char* out_buf);
+typedef int (debug_format_proc_t) (debug_info_t* id, debug_view_t* view,
+ char* out_buf, const char* in_buf);
+typedef int (debug_prolog_proc_t) (debug_info_t* id, debug_view_t* view,
+ char* out_buf);
+
+struct debug_view_s {
+ char name[DEBUG_MAX_PROCF_LEN];
+ debug_prolog_proc_t* prolog_proc;
+ debug_header_proc_t* header_proc;
+ debug_format_proc_t* format_proc;
+ void* private_data;
+};
+
+#define LCRASH_DB_VIEWS 1000
+
+static debug_info_t *debug_area_first = NULL;
+static debug_info_t *debug_area_last = NULL;
+static debug_view_t *debug_views[LCRASH_DB_VIEWS];
+static int initialized = 0;
+static iconv_t ebcdic_ascii_conv = 0;
+
+void s390dbf_usage(command_t * cmd);
+static int add_lcrash_debug_view(debug_view_t *);
+static int dbe_size = 0;
+
+static void
+EBCASC(char *inout, size_t len)
+{
+ iconv(ebcdic_ascii_conv, &inout, &len, &inout, &len);
+}
+
+/*
+ * prints header for debug entry
+ */
+static int
+dflt_header_fn(debug_info_t * id, debug_view_t *view,
+ int area, debug_entry_t * entry, char *out_buf)
+{
+ struct timeval time_val;
+ unsigned long long time;
+ char *except_str;
+ kaddr_t caller;
+ int rc = 0;
+ char *caller_name;
+ 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);
+
+ if (lentry.id.fields.exception)
+ except_str = "*";
+ else
+ except_str = "-";
+ caller = lentry.caller;
+ if(KL_ARCH == KL_ARCH_S390){
+ caller &= 0x7fffffff;
+ }
+ caller_sym = kl_lkup_symaddr(caller);
+ if(caller_sym){
+ caller_name = caller_sym->s_name;
+ offset = caller - kl_funcaddr(caller);
+ }
+ else {
+ sprintf(caller_buf, "%"FMTPTR"x", caller);
+ caller_name = caller_buf;
+ offset = 0;
+ }
+
+ 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;
+}
+
+/*
+ * prints debug header in raw format
+ */
+int
+raw_header_fn(debug_info_t * id, debug_view_t *view,
+ int area, debug_entry_t * entry, char *out_buf)
+{
+ int rc;
+
+ rc = sizeof(debug_entry_t);
+ if (out_buf == NULL)
+ goto out;
+ memcpy(out_buf,entry,sizeof(debug_entry_t));
+ out:
+ return rc;
+}
+
+/*
+ * prints debug data in raw format
+ */
+static int
+raw_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+ int rc;
+
+ rc = id->buf_size;
+ if (out_buf == NULL || in_buf == NULL)
+ goto out;
+ memcpy(out_buf, in_buf, id->buf_size);
+ out:
+ return rc;
+}
+
+/*
+ * prints debug data in hex/ascii format
+ */
+static int
+hex_ascii_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+ int i, rc = 0;
+
+ if (out_buf == NULL || in_buf == NULL) {
+ rc = id->buf_size * 4 + 3;
+ goto out;
+ }
+ for (i = 0; i < id->buf_size; i++) {
+ rc += sprintf(out_buf + rc, "%02x ",
+ ((unsigned char *) in_buf)[i]);
+ }
+ rc += sprintf(out_buf + rc, "| ");
+ for (i = 0; i < id->buf_size; i++) {
+ unsigned char c = in_buf[i];
+ if (!isprint(c))
+ rc += sprintf(out_buf + rc, ".");
+ else
+ rc += sprintf(out_buf + rc, "%c", c);
+ }
+ rc += sprintf(out_buf + rc, "\n");
+ out:
+ return rc;
+}
+
+/*
+ * prints debug data in sprintf format
+ */
+static int
+sprintf_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+#define _BUFSIZE 1024
+ char buf[_BUFSIZE];
+ int i, k, rc = 0, num_longs = 0, num_used_args = 0, num_strings = 0;
+ /* use kaddr_t to store long values of 32bit and 64bit archs here */
+ kaddr_t inbuf_cpy[DEBUG_SPRINTF_MAX_ARGS];
+ /* store ptrs to strings to be deallocated at end of this function */
+ uaddr_t to_dealloc[DEBUG_SPRINTF_MAX_ARGS];
+ kaddr_t addr;
+
+ memset(buf, 0, sizeof(buf));
+ memset(inbuf_cpy, 0, sizeof(inbuf_cpy));
+ memset(to_dealloc, 0, sizeof(to_dealloc));
+
+ if (out_buf == NULL || in_buf == NULL) {
+ rc = id->buf_size * 4 + 3;
+ goto out;
+ }
+
+ /* get the format string into buf */
+ addr = KL_GET_PTR((void*)in_buf);
+ GET_BLOCK(addr, _BUFSIZE, buf);
+
+ k = 0;
+ for (i = 0; buf[i] && (buf[i] != '\n'); i++) {
+ if (buf[i] != '%')
+ continue;
+ if (k == DEBUG_SPRINTF_MAX_ARGS) {
+ fprintf(KL_ERRORFP,
+ "\nToo much parameters in sprinf view (%i)\n"
+ ,k + 1);
+ fprintf(KL_ERRORFP, "Format String: %s)\n", buf);
+ break;
+ }
+ /* for sprintf we have only unsigned long values ... */
+ if (buf[i+1] != 's'){
+ /* we use KL_GET_PTR here to read ulong value */
+ addr = KL_GET_PTR((void*) in_buf + ((k + 1)* KL_NBPW));
+ inbuf_cpy[k] = addr;
+ } else { /* ... or ptrs to strings in debug areas */
+ inbuf_cpy[k] = (uaddr_t) malloc(_BUFSIZE);
+ to_dealloc[num_strings++] = inbuf_cpy[k];
+ addr = KL_GET_PTR((void*) in_buf + ((k + 1)* KL_NBPW));
+ GET_BLOCK(addr, _BUFSIZE,
+ (void*)(uaddr_t)(inbuf_cpy[k]));
+ }
+ k++;
+ }
+
+ /* count of longs fit into one entry */
+ num_longs = id->buf_size / KL_NBPW; /* sizeof(long); */
+ if(num_longs < 1) /* bufsize of entry too small */
+ goto out;
+ if(num_longs == 1) { /* no args, just print the format string */
+ rc = sprintf(out_buf + rc, "%s", buf);
+ goto out;
+ }
+
+ /* number of arguments used for sprintf (without the format string) */
+ num_used_args = MIN(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
+
+ rc = sprintf(out_buf + rc, buf, (uaddr_t)(inbuf_cpy[0]),
+ (uaddr_t)(inbuf_cpy[1]), (uaddr_t)(inbuf_cpy[2]),
+ (uaddr_t)(inbuf_cpy[3]), (uaddr_t)(inbuf_cpy[4]),
+ (uaddr_t)(inbuf_cpy[5]), (uaddr_t)(inbuf_cpy[6]),
+ (uaddr_t)(inbuf_cpy[7]), (uaddr_t)(inbuf_cpy[8]),
+ (uaddr_t)(inbuf_cpy[9]));
+ out:
+ while (num_strings--){
+ free((char*)(to_dealloc[num_strings]));
+ }
+ return rc;
+}
+
+
+/***********************************
+ * functions for debug-views
+ ***********************************/
+
+/*
+ * prints out actual debug level
+ */
+static int
+prolog_level_fn(debug_info_t * id,
+ debug_view_t *view, char *out_buf)
+{
+ int rc = 0;
+
+ if (out_buf == NULL) {
+ rc = 2;
+ goto out;
+ }
+ rc = sprintf(out_buf, "%i\n", id->level);
+ out:
+ return rc;
+}
+
+/*
+ * prints out actual pages_per_area
+ */
+static int
+prolog_pages_fn(debug_info_t * id,
+ debug_view_t *view, char *out_buf)
+{
+ int rc = 0;
+
+ if (out_buf == NULL) {
+ rc = 2;
+ goto out;
+ }
+ rc = sprintf(out_buf, "%i\n", id->pages_per_area_v2);
+ out:
+ return rc;
+}
+
+/*
+ * prints out prolog
+ */
+static int
+prolog_fn(debug_info_t * id,
+ debug_view_t *view, char *out_buf)
+{
+ int rc = 0;
+
+ rc = sprintf(out_buf, "AREA TIME LEVEL EXCEPTION CP CALLING FUNCTION"
+ " + OFFSET DATA\n==================================="
+ "=======================================\n");
+ return rc;
+}
+
+/*
+ * prints debug data in hex format
+ */
+static int
+hex_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+ int i, rc = 0;
+
+ for (i = 0; i < id->buf_size; i++) {
+ rc += sprintf(out_buf + rc, "%02x ",
+ ((unsigned char *) in_buf)[i]);
+ }
+ rc += sprintf(out_buf + rc, "\n");
+ return rc;
+}
+
+/*
+ * prints debug data in ascii format
+ */
+static int
+ascii_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+ int i, rc = 0;
+
+ if (out_buf == NULL || in_buf == NULL) {
+ rc = id->buf_size + 1;
+ goto out;
+ }
+ for (i = 0; i < id->buf_size; i++) {
+ unsigned char c = in_buf[i];
+ if (!isprint(c))
+ rc += sprintf(out_buf + rc, ".");
+ else
+ rc += sprintf(out_buf + rc, "%c", c);
+ }
+ rc += sprintf(out_buf + rc, "\n");
+ out:
+ return rc;
+}
+
+/*
+ * prints debug data in ebcdic format
+ */
+static int
+ebcdic_format_fn(debug_info_t * id, debug_view_t *view,
+ char *out_buf, const char *in_buf)
+{
+ int i, rc = 0;
+
+ if (out_buf == NULL || in_buf == NULL) {
+ rc = id->buf_size + 1;
+ goto out;
+ }
+ for (i = 0; i < id->buf_size; i++) {
+ unsigned char c = in_buf[i];
+ EBCASC(&c, 1);
+ if (!isprint(c))
+ rc += sprintf(out_buf + rc, ".");
+ else
+ rc += sprintf(out_buf + rc, "%c", c);
+ }
+ rc += sprintf(out_buf + rc, "\n");
+ out:
+ return rc;
+}
+
+debug_view_t ascii_view = {
+ "ascii",
+ &prolog_fn,
+ &dflt_header_fn,
+ &ascii_format_fn,
+};
+
+debug_view_t ebcdic_view = {
+ "ebcdic",
+ &prolog_fn,
+ &dflt_header_fn,
+ &ebcdic_format_fn,
+};
+
+debug_view_t hex_view = {
+ "hex",
+ &prolog_fn,
+ &dflt_header_fn,
+ &hex_format_fn,
+};
+
+debug_view_t level_view = {
+ "level",
+ &prolog_level_fn,
+ NULL,
+ NULL,
+};
+
+debug_view_t pages_view = {
+ "pages",
+ &prolog_pages_fn,
+ NULL,
+ NULL,
+};
+
+debug_view_t raw_view = {
+ "raw",
+ NULL,
+ &raw_header_fn,
+ &raw_format_fn,
+};
+
+debug_view_t hex_ascii_view = {
+ "hex_ascii",
+ &prolog_fn,
+ &dflt_header_fn,
+ &hex_ascii_format_fn,
+};
+
+debug_view_t sprintf_view = {
+ "sprintf",
+ &prolog_fn,
+ &dflt_header_fn,
+ &sprintf_format_fn,
+};
+
+
+static debug_entry_t *
+debug_find_oldest_entry(debug_entry_t *entries, int num, int entry_size)
+{
+ debug_entry_t *result, *current;
+ int i;
+ uint64_t clock1, clock2;
+
+ result = entries;
+ current = entries;
+ for (i=0; i < num; i++) {
+ if (current->id.stck == 0)
+ break;
+ clock1 = current->id.fields.clock;
+ clock2 = result->id.fields.clock;
+ clock1 = KL_GET_UINT64(&clock1);
+ clock2 = KL_GET_UINT64(&clock2);
+ if (clock1 < clock2)
+ result = current;
+ current = (debug_entry_t *) ((char *) current + entry_size);
+ }
+ return result;
+}
+
+
+/*
+ * debug_format_output:
+ * - calls prolog, header and format functions of view to format output
+ */
+static int
+debug_format_output_v1(debug_info_t * debug_area, debug_view_t *view,
+ FILE * ofp)
+{
+ int i, j, len;
+ int nr_of_entries;
+ debug_entry_t *act_entry, *last_entry;
+ char *act_entry_data;
+ char buf[2048];
+
+ /* print prolog */
+ if (view->prolog_proc) {
+ len = view->prolog_proc(debug_area, view, buf);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ /* print debug records */
+ if (!(view->format_proc) && !(view->header_proc))
+ goto out;
+ if(debug_area->entry_size <= 0){
+ fprintf(ofp, "Invalid entry_size: %i\n",debug_area->entry_size);
+ goto out;
+ }
+ nr_of_entries = (PAGE_SIZE << debug_area->page_order) / debug_area->entry_size;
+ for (i = 0; i < debug_area->nr_areas; i++) {
+ 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] +
+ (PAGE_SIZE << debug_area->page_order) -
+ debug_area->entry_size);
+ for (j = 0; j < nr_of_entries; j++) {
+ act_entry_data = (char*)act_entry + dbe_size;
+ if (act_entry->id.stck == 0)
+ break; /* empty entry */
+ if (view->header_proc) {
+ len = view->header_proc(debug_area, view, i,
+ act_entry, buf);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ if (view->format_proc) {
+ len = view->format_proc(debug_area, view,
+ buf, act_entry_data);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ act_entry =
+ (debug_entry_t *) (((char *) act_entry) +
+ debug_area->entry_size);
+ if (act_entry > last_entry)
+ act_entry = debug_area->areas[i];
+ }
+ }
+ out:
+ return 1;
+}
+
+/*
+ * debug_format_output_v2:
+ * - calls prolog, header and format functions of view to format output
+ */
+static int
+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;
+ char *act_entry_data;
+ char buf[2048];
+
+ /* print prolog */
+ if (view->prolog_proc) {
+ len = view->prolog_proc(debug_area, view, buf);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ /* print debug records */
+ if (!(view->format_proc) && !(view->header_proc))
+ goto out;
+ if(debug_area->entry_size <= 0){
+ fprintf(ofp, "Invalid entry_size: %i\n",debug_area->entry_size);
+ goto out;
+ }
+ for (i = 0; i < debug_area->nr_areas; i++) {
+ int nr_entries_per_page = PAGE_SIZE/debug_area->entry_size;
+ for (j = 0; j < debug_area->pages_per_area_v2; j++) {
+ 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)
+ break; /* empty entry */
+ if (view->header_proc) {
+ len = view->header_proc(debug_area,
+ view, i, act_entry, buf);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ if (view->format_proc) {
+ len = view->format_proc(debug_area,
+ view, buf, act_entry_data);
+ fwrite(buf,len, 1, ofp);
+ memset(buf, 0, 2048);
+ }
+ act_entry = (debug_entry_t *) (((char *)
+ act_entry) + debug_area->entry_size);
+ }
+ }
+ }
+out:
+ return 1;
+}
+
+static debug_info_t *
+find_debug_area(const char *area_name)
+{
+ debug_info_t* act_debug_info = debug_area_first;
+ while(act_debug_info != NULL){
+ if (strcmp(act_debug_info->name, area_name) == 0)
+ return act_debug_info;
+ act_debug_info = act_debug_info->next;
+ }
+ return NULL;
+}
+
+static void
+dbf_init(void)
+{
+ if (!initialized) {
+ if(dbf_version >= DBF_VERSION_V2)
+ add_lcrash_debug_view(&pages_view);
+ add_lcrash_debug_view(&ascii_view);
+ add_lcrash_debug_view(&level_view);
+ add_lcrash_debug_view(&ebcdic_view);
+ add_lcrash_debug_view(&hex_view);
+ add_lcrash_debug_view(&hex_ascii_view);
+ add_lcrash_debug_view(&sprintf_view);
+ add_lcrash_debug_view(&raw_view);
+ ebcdic_ascii_conv = iconv_open("ISO-8859-1", "EBCDIC-US");
+ initialized = 1;
+ }
+}
+
+static debug_view_t*
+get_debug_view(kaddr_t addr)
+{
+ void* k_debug_view;
+ int k_debug_view_size;
+ debug_view_t* rc;
+
+ rc = (debug_view_t*)malloc(sizeof(debug_view_t));
+ memset(rc, 0, sizeof(debug_view_t));
+
+ k_debug_view_size = kl_struct_len("debug_view");
+ k_debug_view = malloc(k_debug_view_size);
+ GET_BLOCK(addr, k_debug_view_size, k_debug_view);
+ strncpy(rc->name,K_PTR(k_debug_view,"debug_view","name"),
+ DEBUG_MAX_PROCF_LEN);
+
+ free(k_debug_view);
+ return rc;
+}
+
+static void
+free_debug_view(debug_view_t* view)
+{
+ if(view)
+ free(view);
+}
+
+static void
+debug_get_areas_v1(debug_info_t* db_info, void* k_dbi)
+{
+ kaddr_t mem_pos;
+ kaddr_t dbe_addr;
+ int area_size, i;
+
+ /* get areas */
+ /* place to hold ptrs to debug areas in lcrash */
+ area_size = PAGE_SIZE << db_info->page_order;
+ db_info->areas = (void**)malloc(db_info->nr_areas * sizeof(void *));
+ memset(db_info->areas, 0, db_info->nr_areas * sizeof(void *));
+ mem_pos = (kaddr_t) KL_UINT(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);
+ /* read raw data for debug area */
+ GET_BLOCK(dbe_addr, area_size, db_info->areas[i]);
+ mem_pos += KL_NBPW;
+ }
+}
+
+static void
+debug_get_areas_v2(debug_info_t* db_info, void* k_dbi)
+{
+ kaddr_t area_ptr;
+ kaddr_t page_array_ptr;
+ kaddr_t page_ptr;
+ int i,j;
+ db_info->areas_v2=(void***)malloc(db_info->nr_areas * sizeof(void **));
+ area_ptr = (kaddr_t) KL_UINT(k_dbi,"debug_info","areas");
+ for (i = 0; i < db_info->nr_areas; i++) {
+ db_info->areas_v2[i] = (void**)malloc(db_info->pages_per_area_v2
+ * sizeof(void*));
+ page_array_ptr = KL_VREAD_PTR(area_ptr);
+ for(j=0; j < db_info->pages_per_area_v2; j++) {
+ page_ptr = KL_VREAD_PTR(page_array_ptr);
+ db_info->areas_v2[i][j] = (void*)malloc(PAGE_SIZE);
+ /* read raw data for debug area */
+ GET_BLOCK(page_ptr, PAGE_SIZE, db_info->areas_v2[i][j]);
+ page_array_ptr += KL_NBPW;
+ }
+ area_ptr += KL_NBPW;
+ }
+}
+
+static debug_info_t*
+get_debug_info(kaddr_t addr,int get_areas)
+{
+ void *k_dbi;
+ kaddr_t mem_pos;
+ kaddr_t view_addr;
+ debug_info_t* db_info;
+ int i;
+ int dbi_size;
+
+ /* get sizes of kernel structures */
+ if(!(dbi_size = kl_struct_len("debug_info"))){
+ fprintf (KL_ERRORFP,
+ "Could not determine sizeof(struct debug_info)\n");
+ return(NULL);
+ }
+ if(!(dbe_size = kl_struct_len("__debug_entry"))){
+ fprintf(KL_ERRORFP,
+ "Could not determine sizeof(struct __debug_entry)\n");
+ return(NULL);
+ }
+
+ /* get kernel debug_info structure */
+ k_dbi = malloc(dbi_size);
+ GET_BLOCK(addr, dbi_size, k_dbi);
+
+ db_info = (debug_info_t*)malloc(sizeof(debug_info_t));
+ memset(db_info, 0, sizeof(debug_info_t));
+
+ /* copy members */
+ db_info->level = KL_INT(k_dbi,"debug_info","level");
+ db_info->nr_areas = KL_INT(k_dbi,"debug_info","nr_areas");
+ db_info->pages_per_area_v2= KL_INT(k_dbi,"debug_info","pages_per_area");
+ db_info->page_order = KL_INT(k_dbi,"debug_info","page_order");
+ db_info->buf_size = KL_INT(k_dbi,"debug_info","buf_size");
+ db_info->entry_size = KL_INT(k_dbi,"debug_info","entry_size");
+ db_info->next_dbi = KL_UINT(k_dbi,"debug_info","next");
+ db_info->prev_dbi = KL_UINT(k_dbi,"debug_info","prev");
+ db_info->addr = addr;
+ strncpy(db_info->name,K_PTR(k_dbi,"debug_info","name"),
+ DEBUG_MAX_PROCF_LEN);
+
+
+ if(get_areas){
+ if(dbf_version == DBF_VERSION_V1)
+ debug_get_areas_v1(db_info,k_dbi);
+ else
+ debug_get_areas_v2(db_info,k_dbi);
+ } else {
+ db_info->areas = NULL;
+ }
+
+ /* get views */
+ mem_pos = (uaddr_t) K_PTR(k_dbi,"debug_info","views");
+ memset(&db_info->views, 0, DEBUG_MAX_VIEWS * sizeof(void*));
+ for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+ view_addr = KL_GET_PTR((void*)(uaddr_t)mem_pos);
+ if(view_addr == 0){
+ break;
+ } else {
+ db_info->views[i] = get_debug_view(view_addr);
+ }
+ mem_pos += KL_NBPW;
+ }
+ free(k_dbi);
+ return db_info;
+}
+
+static void
+free_debug_info_v1(debug_info_t * db_info)
+{
+ int i;
+ if(db_info->areas){
+ for (i = 0; i < db_info->nr_areas; i++) {
+ free(db_info->areas[i]);
+ }
+ }
+ for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+ free_debug_view(db_info->views[i]);
+ }
+ free(db_info->areas);
+ free(db_info);
+}
+
+static void
+free_debug_info_v2(debug_info_t * db_info)
+{
+ int i,j;
+ if(db_info->areas) {
+ for (i = 0; i < db_info->nr_areas; i++) {
+ for(j = 0; j < db_info->pages_per_area_v2; j++) {
+ free(db_info->areas_v2[i][j]);
+ }
+ free(db_info->areas[i]);
+ }
+ free(db_info->areas);
+ db_info->areas = NULL;
+ }
+ for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+ free_debug_view(db_info->views[i]);
+ }
+ free(db_info);
+}
+
+static int
+get_debug_areas(void)
+{
+ kaddr_t act_debug_area;
+ syment_t *debug_sym;
+ debug_info_t *act_debug_area_cpy;
+
+ if(!(debug_sym = kl_lkup_symname("debug_area_first"))){
+ printf("Did not find debug_areas");
+ return -1;
+ }
+ act_debug_area = KL_VREAD_PTR(debug_sym->s_addr);
+ while(act_debug_area != 0){
+ act_debug_area_cpy = get_debug_info(act_debug_area,0);
+ act_debug_area = act_debug_area_cpy->next_dbi;
+ if(debug_area_first == NULL){
+ debug_area_first = act_debug_area_cpy;
+ } else {
+ debug_area_last->next = act_debug_area_cpy;
+ }
+ debug_area_last = act_debug_area_cpy;
+ }
+ return 0;
+}
+
+static void
+free_debug_areas(void)
+{
+ debug_info_t* next;
+ debug_info_t* act_debug_info = debug_area_first;
+
+ while(act_debug_info != NULL){
+ next = act_debug_info->next;
+ if(dbf_version == DBF_VERSION_V1)
+ free_debug_info_v1(act_debug_info);
+ else
+ free_debug_info_v2(act_debug_info);
+ act_debug_info = next;
+ }
+
+ debug_area_first = NULL;
+ debug_area_last = NULL;
+}
+
+static debug_view_t *
+find_lcrash_debug_view(const char *name)
+{
+ int i;
+ for (i = 0; (i < LCRASH_DB_VIEWS) && (debug_views[i] != NULL); i++) {
+ if (strcmp(debug_views[i]->name, name) == 0)
+ return debug_views[i];
+ }
+ return NULL;
+}
+
+static void
+print_lcrash_debug_views(FILE * ofp)
+{
+ int i;
+ fprintf(ofp, "REGISTERED VIEWS\n");
+ fprintf(ofp, "=====================\n");
+ for (i = 0; i < LCRASH_DB_VIEWS; i++) {
+ if (debug_views[i] == NULL) {
+ return;
+ }
+ fprintf(ofp, " - %s\n", debug_views[i]->name);
+ }
+}
+
+static int
+add_lcrash_debug_view(debug_view_t *view)
+{
+ int i;
+ for (i = 0; i < LCRASH_DB_VIEWS; i++) {
+ if (debug_views[i] == NULL) {
+ debug_views[i] = view;
+ return 0;
+ }
+ if (strcmp(debug_views[i]->name, view->name) == 0)
+ return -1;
+ }
+ return -1;
+}
+
+static int
+list_one_view(char *area_name, char *view_name, command_t * cmd)
+{
+ debug_info_t *db_info;
+ debug_view_t *db_view;
+
+ if ((db_info = find_debug_area(area_name)) == NULL) {
+ fprintf(cmd->efp, "Debug log '%s' not found!\n", area_name);
+ return -1;
+ }
+
+ db_info = get_debug_info(db_info->addr,1);
+
+ if ((db_view = find_lcrash_debug_view(view_name)) == NULL) {
+ fprintf(cmd->efp, "View '%s' not registered!\n", view_name);
+ return -1;
+ }
+ if(dbf_version == DBF_VERSION_V1){
+ debug_format_output_v1(db_info, db_view, cmd->ofp);
+ free_debug_info_v1(db_info);
+ } else {
+ debug_format_output_v2(db_info, db_view, cmd->ofp);
+ free_debug_info_v2(db_info);
+ }
+ return 0;
+}
+
+static int
+list_areas(FILE * ofp)
+{
+ debug_info_t* act_debug_info = debug_area_first;
+ fprintf(ofp, "Debug Logs:\n");
+ fprintf(ofp, "==================\n");
+ while(act_debug_info != NULL){
+ fprintf(ofp, " - %s\n", act_debug_info->name);
+ act_debug_info = act_debug_info->next;
+ }
+ return 0;
+}
+
+static int
+list_one_area(const char *area_name, command_t * cmd)
+{
+ debug_info_t *db_info;
+ int i;
+ if ((db_info = find_debug_area(area_name)) == NULL) {
+ fprintf(cmd->efp, "Debug log '%s' not found!\n", area_name);
+ return -1;
+ }
+ fprintf(cmd->ofp, "INSTALLED VIEWS FOR '%s':\n", area_name);
+ fprintf(cmd->ofp, "================================================"
+ "==============================\n");
+ for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+ if (db_info->views[i] != NULL) {
+ fprintf(cmd->ofp, " - %s ", db_info->views[i]->name);
+ if (find_lcrash_debug_view(db_info->views[i]->name))
+ fprintf(cmd->ofp, "(available)\n");
+ else
+ fprintf(cmd->ofp, "(not available)\n");
+ }
+ }
+ fprintf(cmd->ofp, "================================================="
+ "=============================\n");
+ return 0;
+}
+
+#ifdef DBF_DYNAMIC_VIEWS
+static int
+load_debug_view(const char *path, command_t * cmd)
+{
+ void *library;
+ const char *error;
+ debug_view_t *(*view_init_func) (void);
+
+ library = dlopen(path, RTLD_LAZY);
+ if (library == NULL) {
+ fprintf(cmd->efp, "Could not open %s: %s\n", path, dlerror());
+ return (1);
+ }
+
+ dlerror();
+
+ view_init_func = dlsym(library, "debug_view_init");
+ error = dlerror();
+
+ if (error) {
+ fprintf(stderr, "could not find debug_view_init(): %s\n",
+ error);
+ exit(1);
+ }
+
+ add_lcrash_debug_view((*view_init_func) ());
+
+ fprintf(cmd->ofp, "view %s loaded\n", path);
+ fflush(stdout);
+ return 0;
+}
+#endif
+
+/*
+ * s390dbf_cmd() -- Run the 's390dbf' command.
+ */
+int
+s390dbf_cmd(command_t * cmd)
+{
+ syment_t *dbf_version_sym;
+ int rc = 0;
+
+ /* check version */
+
+ if(!(dbf_version_sym = kl_lkup_symname("debug_feature_version"))){
+ fprintf(KL_ERRORFP,
+ "Could not determine debug_feature_version\n");
+ return -1;
+ }
+
+ dbf_version = KL_VREAD_UINT32(dbf_version_sym->s_addr);
+
+ if ((dbf_version != DBF_VERSION_V1) && (dbf_version != DBF_VERSION_V2)){
+ 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);
+ return -1;
+ }
+
+ dbf_init();
+
+ if (cmd->flags & C_ALL) {
+ return (0);
+ }
+#ifdef DBF_DYNAMIC_VIEWS
+ if (cmd->flags & LOAD_FLAG) {
+ printf("loading: %s\n", cmd->args[0]);
+ return (load_debug_view(cmd->args[0], cmd));
+ }
+#endif
+ if (cmd->flags & VIEWS_FLAG) {
+ print_lcrash_debug_views(cmd->ofp);
+ return (0);
+ }
+ if (cmd->nargs > 2) {
+ s390dbf_usage(cmd);
+ return (1);
+ }
+
+ if(get_debug_areas() == -1)
+ return -1;
+
+ switch (cmd->nargs) {
+ case 0:
+ rc = list_areas(cmd->ofp);
+ break;
+ case 1:
+ rc = list_one_area(cmd->args[0], cmd);
+ break;
+ case 2:
+ rc = list_one_view(cmd->args[0], cmd->args[1], cmd);
+ break;
+ }
+
+ free_debug_areas();
+
+ return rc;
+}
+
+#define _S390DBF_USAGE " [-v] [debug log] [debug view]"
+
+/*
+ * s390dbf_usage() -- Print the usage string for the 's390dbf' command.
+ */
+void
+s390dbf_usage(command_t * cmd)
+{
+ CMD_USAGE(cmd, _S390DBF_USAGE);
+}
+
+/*
+ * s390 debug feature command for crash
+ */
+
+char *help_s390dbf[] = {
+ "s390dbf",
+ "s390dbf prints out debug feature logs",
+ "[-v] [debug_log] [debug_log view]",
+ "",
+ "Display Debug logs:",
+ " + If called without parameters, all active debug logs are listed.",
+ " + If called with '-v', all debug views which are available to",
+ " 'crash' are listed",
+ " + If called with the name of a debug log, all debug-views for which",
+ " the debug-log has registered are listed. It is possible thatsome",
+ " of the debug views are not available to 'crash'.",
+ " + If called with the name of a debug-log and an available viewname,",
+ " the specified view is printed.",
+ NULL
+};
+
+void cmd_s390dbf()
+{
+ int i,c;
+
+ command_t cmd = {
+ .ofp = stdout,
+ .efp = stderr,
+ .cmdstr = "s390dbf",
+ .command = "s390dbf",
+ };
+
+ cmd.nargs=argcnt - 1;
+ for (i=1; i < argcnt; i++)
+ cmd.args[i-1] = args[i];
+
+ while ((c = getopt(argcnt, args, "v")) != EOF) {
+ switch(c) {
+ case 'v':
+ cmd.flags |= VIEWS_FLAG;
+ break;
+ default:
+ s390dbf_usage(&cmd);
+ return 1;
+ }
+ }
+ s390dbf_cmd(&cmd);
+}
+
+#endif
18 years, 3 months
HZ undefined in libc headers
by Olaf Hering
Upcoming glibc header files have no visible definition of HZ anymore. A
glibc macro exist to query the current tick rate. This macro will likely
work for all other apps, Unfortunately crash wants to know the HZ value
of the crashed kernel.
My patch makes the assumption that the dump file is analyzed on a system
similar to the crashed one. I dont know how accurate that is.
If I read the source right, HZ is currently forced to be 1000 which is
not true either. Newer kernels can be configured for 100, 250 and 1000.
Ideally, the core file exports HZ in some way. I see cfq_slice_async is
used to get the HZ value in task_init().
---
alpha.c | 2 +-
ia64.c | 2 +-
ppc.c | 4 +---
ppc64.c | 4 +---
s390.c | 2 +-
s390x.c | 2 +-
x86.c | 4 +---
x86_64.c | 4 +---
8 files changed, 8 insertions(+), 16 deletions(-)
Index: crash-4.0-2.33/alpha.c
===================================================================
--- crash-4.0-2.33.orig/alpha.c
+++ crash-4.0-2.33/alpha.c
@@ -186,7 +186,7 @@ alpha_init(int when)
"irq_desc", NULL, 0);
else
machdep->nr_irqs = 0;
- machdep->hz = HZ;
+ machdep->hz = sysconf(_SC_CLK_TCK);
break;
case POST_INIT:
Index: crash-4.0-2.33/ppc.c
===================================================================
--- crash-4.0-2.33.orig/ppc.c
+++ crash-4.0-2.33/ppc.c
@@ -135,9 +135,7 @@ ppc_init(int when)
"irq_desc", NULL, 0);
else
machdep->nr_irqs = 0;
- machdep->hz = HZ;
- if (THIS_KERNEL_VERSION >= LINUX(2,6,0))
- machdep->hz = 1000;
+ machdep->hz = sysconf(_SC_CLK_TCK);
machdep->section_size_bits = _SECTION_SIZE_BITS;
machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
break;
Index: crash-4.0-2.33/ppc64.c
===================================================================
--- crash-4.0-2.33.orig/ppc64.c
+++ crash-4.0-2.33/ppc64.c
@@ -237,9 +237,7 @@ ppc64_init(int when)
*/
BZERO(&machdep->machspec->hwintrstack,
NR_CPUS*sizeof(ulong));
- machdep->hz = HZ;
- if (THIS_KERNEL_VERSION >= LINUX(2,6,0))
- machdep->hz = 1000;
+ machdep->hz = sysconf(_SC_CLK_TCK);
/*
* IRQ stacks are introduced in 2.6 and also configurable.
*/
Index: crash-4.0-2.33/s390.c
===================================================================
--- crash-4.0-2.33.orig/s390.c
+++ crash-4.0-2.33/s390.c
@@ -158,7 +158,7 @@ s390_init(int when)
machdep->nr_irqs = 0; /* TBD */
machdep->vmalloc_start = s390_vmalloc_start;
machdep->dump_irq = s390_dump_irq;
- machdep->hz = HZ;
+ machdep->hz = sysconf(_SC_CLK_TCK);
break;
case POST_INIT:
Index: crash-4.0-2.33/s390x.c
===================================================================
--- crash-4.0-2.33.orig/s390x.c
+++ crash-4.0-2.33/s390x.c
@@ -173,7 +173,7 @@ s390x_init(int when)
machdep->nr_irqs = 0; /* TBD */
machdep->vmalloc_start = s390x_vmalloc_start;
machdep->dump_irq = s390x_dump_irq;
- machdep->hz = HZ;
+ machdep->hz = sysconf(_SC_CLK_TCK);
break;
case POST_INIT:
Index: crash-4.0-2.33/x86.c
===================================================================
--- crash-4.0-2.33.orig/x86.c
+++ crash-4.0-2.33/x86.c
@@ -1775,9 +1775,7 @@ x86_init(int when)
"irq_desc", NULL, 0);
else
machdep->nr_irqs = 224; /* NR_IRQS */
- machdep->hz = HZ;
- if (THIS_KERNEL_VERSION >= LINUX(2,6,0))
- machdep->hz = 1000;
+ machdep->hz = sysconf(_SC_CLK_TCK);
if (machdep->flags & PAE){
machdep->section_size_bits = _SECTION_SIZE_BITS_PAE;
Index: crash-4.0-2.33/x86_64.c
===================================================================
--- crash-4.0-2.33.orig/x86_64.c
+++ crash-4.0-2.33/x86_64.c
@@ -238,9 +238,7 @@ x86_64_init(int when)
machdep->nr_irqs = 224; /* NR_IRQS (at least) */
machdep->vmalloc_start = x86_64_vmalloc_start;
machdep->dump_irq = x86_64_dump_irq;
- machdep->hz = HZ;
- if (THIS_KERNEL_VERSION >= LINUX(2,6,0))
- machdep->hz = 1000;
+ machdep->hz = sysconf(_SC_CLK_TCK);
machdep->section_size_bits = _SECTION_SIZE_BITS;
machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
if (XEN()) {
Index: crash-4.0-2.33/ia64.c
===================================================================
--- crash-4.0-2.33.orig/ia64.c
+++ crash-4.0-2.33/ia64.c
@@ -205,7 +205,7 @@ ia64_init(int when)
else if (symbol_exists("_irq_desc"))
ARRAY_LENGTH_INIT(machdep->nr_irqs, irq_desc,
"_irq_desc", NULL, 0);
- machdep->hz = 1024;
+ machdep->hz = sysconf(_SC_CLK_TCK);
ia64_create_memmap();
break;
18 years, 4 months
Re: [PATCH] IA-64 4-level page table support
by Dave Anderson
> Attached is a patch that adds 4-level page table support to the IA-64
> architecture. I followed the way PPC used the machdep command line
> argument to force it. Since this is truly a CONFIG option on IA-64, I
> have also added a routine to parse the required information out of
> IKCONFIG if it's available. I'm thinking about requiring IKCONFIG for
> LKCD, because it just makes life easer.
>
> As a side note, I decided I hate how everything is piled into defs.h
> and separated by ifdefs. Dave, how do you feel about breaking defs.h
> up into a header for each arch, i.e. ia64_defs.h, ppc_def.h, etc, and
> a small common defs.h?
>
> Thanks,
>
> Troy
>
Hi Troy,
Nice work...
The only issues I see is that the read_config() and read_config_err()
should probably go into a common file in case we ever need them for
other configuration-related stuff in the future, and couple of the malloc()
error messages in read_config() are cut-and-pasted and refer to
"ia64_memmap".
I'll give it a run against a 3 leveler to make sure nothing breaks.
As far as the defs.h split-up, I have no argument against doing that.
Thanks,
Dave
18 years, 4 months
crash version 4.0-2.33 is available / vacation notice
by Dave Anderson
> Can you be more specific? The code is certainly not supposed to
> be "effectively commented out":
>
>
Mea culpa -- the function returns NULL first thing,
causing some compilers to rightfully barf...
static char *
x86_xen_kdump_load_page_PAE(ulong kvaddr, char *pgbuf)
{
return NULL;
ulonglong *entry;
ulonglong *up;
ulong mfn;
...
The function was originally a stub, but later I added the
(untested) code, and left the return in place. The VAlinux
guys had furnished me with a non-PAE xen kdump vmcore, and
since there aren't any xen kdump *PAE* dumpfiles in existence
on the planet that I'm aware of, it shouldn't hurt, of course
unless your compiler won't accept it...
Anyway, 4.0-2.33 is available if you need it.
Also, I will be going on vacation -- basically starting right
now -- and won't be back until July 31st. I don't plan on
being internet-visible until then, so if anything comes up
between now and then that needs me, it'll have to wait...
Dave
18 years, 4 months
[PATCH] IA-64 4-level page table support
by Troy Heber
Attached is a patch that adds 4-level page table support to the IA-64
architecture. I followed the way PPC used the machdep command line
argument to force it. Since this is truly a CONFIG option on IA-64, I
have also added a routine to parse the required information out of
IKCONFIG if it's available. I'm thinking about requiring IKCONFIG for
LKCD, because it just makes life easer.
As a side note, I decided I hate how everything is piled into defs.h
and separated by ifdefs. Dave, how do you feel about breaking defs.h
up into a header for each arch, i.e. ia64_defs.h, ppc_def.h, etc, and
a small common defs.h?
Thanks,
Troy
18 years, 4 months