Logo Search packages:      
Sourcecode: lcrash version File versions  Download package

report_s390.c

/*
 * $Id: report_s390.c,v 1.1 2004/12/21 23:26:17 tjm Exp $
 *
 * This file is part of lcrash, an analysis tool for Linux memory dumps.
 *
 * Created by Silicon Graphics, Inc.
 * Contributions by IBM, and others
 *
 * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version. See the file COPYING for more
 * information.
 */

#include <lcrash.h>

void print_active_idle_stacks(FILE* ofp);

/*
 * print_active_stacks_2_5
 *
 * print stack backtraces of all currently running tasks (kernel 2.5 and UL)
 */

void print_active_stacks_2_5(FILE* ofp)
{
      syment_t *sp;
      int rq_size;
      char* runqueues;
      char* act_runqueue;
      int i;

      rq_size =  kl_struct_len("runqueue");
      if(KL_ERROR){
            goto out;
      }
      if (!(sp = kl_lkup_symname("runqueues"))) {
            goto out;
      }
      runqueues = (char *)kl_alloc_block(rq_size * KL_NUM_CPUS, K_TEMP);
      GET_BLOCK(sp->s_addr,rq_size * KL_NUM_CPUS,runqueues);
      if(KL_ERROR){
            goto out;
      }

      act_runqueue = runqueues;
      for(i = 0; i < KL_NUM_CPUS; i++){
            uint64_t addr;
            addr =  kl_kaddr(act_runqueue,"runqueue","curr");
            TASK_TRACE(addr, 0, ofp);
            act_runqueue += rq_size;
      }
out:
      return;
}

/*
 * test_bit
 *
 * Implementation from include/asm-s390/bitops.h
 */
static inline int test_bit(unsigned long nr, const void *ptr)
{
      unsigned long addr;
      unsigned char ch;

      addr = ((unsigned long)ptr)+((nr ^ (KL_PTRSZ - 8)) >> 3);
      ch = *(unsigned char *) addr;
      return (ch >> (nr & 7)) & 1;
}

/*
 * print_active_stacks_2_6
 *
 * print stack backtraces of all currently running tasks (kernel 2.6)
 */
void print_active_stacks_2_6(FILE* ofp)
{
      /* Linux 2.6 Scheduler  */

      int i, rq_size,max_cpus;
      char* runqueue = NULL;
      kaddr_t rq_addr;
      uint64_t cpu_online_map = 0;
      syment_t *sp;

      /* FIXME: This currently only works for max 32/64 cpus (31/64 bit) */

      sp = kl_lkup_symname("cpu_online_map");
      if(!sp){
            fprintf(KL_ERRORFP,"cannot access cpu_online_map\n");
            goto out;
      }
      if(PTRSZ32){
            kl_readmem(sp->s_addr, 4 , &cpu_online_map);
            max_cpus = 32;
      } else {
            kl_readmem(sp->s_addr, 8 , &cpu_online_map);
            max_cpus = 64;
      }

      rq_size =  kl_struct_len("runqueue");
      if(KL_ERROR || (rq_size == 0)){
            fprintf(KL_ERRORFP,"type >struct runqueue< not in Kerntypes\n");
            goto out;
      }
      runqueue = (char *)kl_alloc_block(rq_size, K_TEMP);
      if(!runqueue){
            fprintf(KL_ERRORFP,"malloc failed\n");
            goto out;
      }
      for(i = 0; i < max_cpus; i++){
            if(!test_bit(i,(unsigned long*)&cpu_online_map))
                  continue;
            rq_addr = symaddr_per_cpu_2_6("runqueues",i);
            if(!rq_addr){
                  fprintf(KL_ERRORFP,"cannot find per cpu symbol 'runqueues'\n");
                  goto out;
            }
            GET_BLOCK(rq_addr, rq_size,runqueue);
            if(KL_ERROR){
                  fprintf(KL_ERRORFP,"GET_BLOCK failed\n");
                  goto out;
            }
            rq_addr = kl_kaddr(runqueue,"runqueue","curr");
            TASK_TRACE(rq_addr, 0, ofp);
      }
out:
      if(runqueue)
            kl_free_block(runqueue);
}

/*
 * print_active_stacks
 * 
 * print stack backtraces of all currently running tasks (kernel 2.2 + 2.4)
 */

void print_active_stacks_22_24(FILE* ofp)
{
        kaddr_t addr,first_task_addr;
        void *tsp;
 
        if (!(tsp = kl_alloc_block(TASK_STRUCT_SZ, K_TEMP))) {
                return;
        }
        get_first_task(&first_task_addr);
        addr = first_task_addr;
        do {
                if (kl_get_task_struct(addr, 2, tsp)) {
                        break;
                }
                if(task_has_cpu(addr,tsp)) {
                        void* lc;
                        lc = get_cpu_lowcore_s390(task_cpu(tsp));
                        if(!lc){
                                fprintf(ofp, "TASK : %#"FMTPTR"x (%s)\n",
                                        addr, (char*)K_PTR(tsp, "task_struct", "comm"));
                                fprintf(ofp,"Error: Cannot locate lowcore\n");
                        } else {
                                TASK_TRACE(addr, 0, ofp);
                        }
                        free_cpu_lowcore_s390(lc);
                }
                addr = (kaddr_t)KL_INT(tsp, "task_struct", "next_task");
        } while (addr != first_task_addr);
        kl_free_block(tsp);
        fprintf(ofp, "\n");
        fprintf(ofp, "=================================\n"
                     "STACK TRACE OF RUNNING IDLE TASKS\n"
                     "=================================\n\n");
        print_active_idle_stacks(ofp);
}

/*
 * print_active_stacks
 *
 * print stack backtraces of all currently running tasks (kernel 2.2 + 2.4)
 */

void print_active_stacks(FILE* ofp)
{
      if (kl_lkup_symname("per_cpu__runqueues")){
            /* Linux 2.6 */
            print_active_stacks_2_6(ofp);
      } else if (kl_lkup_symname("runqueues")){
            /* Linux 2.5 and UL */
            print_active_stacks_2_5(ofp);
      } else if (kl_lkup_symname("init_task_union")) {
            /* Linux 2.2 + 2.4 */
            print_active_stacks_22_24(ofp);
      }
}

/*
 * print_active_idle_stacks
 *
 * print stack backtraces of all active idle tasks 
 */

void print_active_idle_stacks(FILE* ofp)
{
        kaddr_t addr;
        syment_t *sp;
        void *tsp;
        int i;

      if (LINUX_2_2_X(KL_LINUX_RELEASE)) {
            sp =  kl_lkup_symname("task");
      }
      else{
            sp = kl_lkup_symname("init_tasks");
      }
        if (sp) {
                void* task_list;
                if (!(tsp = kl_alloc_block(TASK_STRUCT_SZ, K_TEMP))) { 
                  return;
                }
                if(!(task_list = kl_alloc_block(KL_NBPW * KL_NUM_CPUS,
                                    K_TEMP))) {
                        goto alloc_task_list_failed;
                }
                GET_BLOCK(sp->s_addr, KL_NBPW * KL_NUM_CPUS, task_list);
                for(i = 1; i < KL_NUM_CPUS; i++)
                {
                        addr = KL_GET_PTR(task_list+(i*KL_NBPW));
                        if (kl_get_task_struct(addr, 2, tsp)) {
                                break;
                        }
                        if( task_has_cpu(addr,tsp) )
                        {
                                void* lc; /* lowcore */
                                lc = get_cpu_lowcore_s390(task_cpu(tsp));
                                if(!lc){
                                        fprintf(ofp,
                                    "TASK : %#"FMTPTR"x (%s)\n",
                                    addr,
                                    (char*)K_PTR(tsp,
                                               "task_struct",
                                               "comm"));
                                        fprintf(ofp,"Error: "
                                    "Cannot locate lowcore\n");
                                } else {
                                        TASK_TRACE(addr, 0, ofp);
                                }
                                free_cpu_lowcore_s390(lc);
                        }
                        addr = (kaddr_t)KL_INT(tsp,"task_struct","next_task");
                }
alloc_task_list_failed:
                kl_free_block(tsp);
        }
}

/*
 * do_report_s390() -- generate an s390 lcrash report.
 */
int
do_report_s390(int flags, FILE *ofp)
{
      time_t                 curtime;
      kl_dump_header_s390sa_t dha;
      struct timeval         h_time;
      char *                 utsname;
      char*                  h_dump_type;
      uint64_t               h_cpu_id;

      /* get the dump header 
       */
      if (lseek(MIP->core_fd, 0, SEEK_SET) < 0) {
            fprintf(ofp, "Error: Cannot lseek() to get the dump header "
                  "from the dump file!\n");
            return(1);
      }

      if (read(MIP->core_fd, (char *)&dha,
            sizeof(dha)) != sizeof(dha)) {
                  fprintf(ofp, "Error: Cannot read() dump header "
                        "from dump file!\n");
                  return(1);
      }

      /* values of dump header must be byte swapped
       */
      kl_s390tod_to_timeval(KL_GET_UINT64(&dha.tod), &h_time);
      h_dump_type    = "S390";
      h_cpu_id       = KL_GET_UINT64(&dha.cpu_id);

      fprintf(ofp,
            "=======================\n"
            "LCRASH CORE FILE REPORT\n"
            "=======================\n\n");

      curtime = time((time_t *)0);
      fprintf(ofp, "REPORT CREATED ON:\n    %s\n\n", ctime(&curtime));
      fprintf(ofp, "DUMP CREATED ON:\n    %s\n\n", ctime(&h_time.tv_sec));
/*    fprintf(ofp, "MAP:\n    %s\n\nDUMP:\n    %s\n\n", map, dump); */

      fprintf(ofp,
            "================\n"
            "COREFILE SUMMARY\n"
            "================\n\n");

      fprintf(ofp, "  dump type: %s\n\n",h_dump_type);

      fprintf(ofp,
            "===================\n"
            "UTSNAME INFORMATION\n"
            "===================\n\n");

      if((utsname = get_utsname())){
            fprintf(ofp, "\n");
            fprintf(ofp, "   sysname : %s\n", (char*)
                  K_PTR(utsname, NEW_UTSNAME, "sysname"));
            fprintf(ofp, "  nodename : %s\n", (char*)
                  K_PTR(utsname, NEW_UTSNAME, "nodename"));
            fprintf(ofp, "   release : %s\n", (char*)
                  K_PTR(utsname, NEW_UTSNAME, "release"));
            fprintf(ofp, "   version : %s\n", (char*)
                  K_PTR(utsname, NEW_UTSNAME, "version"));
            fprintf(ofp, "   machine : %s\n", (char*)
                  K_PTR(utsname, NEW_UTSNAME, "machine"));
            fprintf(ofp, "domainname : %s\n", (char*)
                  K_PTR(utsname, NEW_UTSNAME, "domainname"));
            kl_free_block(utsname);
      } else {
            fprintf(ofp, "COULD NOT GET system_utsname!\n\n");
      }     
      fprintf(ofp, "\n");
      fprintf(ofp, "s390 cpuid : %#018"FMT64"x\n\n", h_cpu_id);
      fprintf(ofp,
            "===============\n"
            "LOG BUFFER DUMP\n"
            "===============\n\n");

      /* print out the system log
       */
      print_log_buf(ofp);
      fprintf(ofp, "\n\n");

      fprintf(ofp,
            "====================\n"
            "CURRENT SYSTEM TASKS\n"
            "====================\n\n");

      print_active_tasks(flags, ofp);

      fprintf(ofp, "\n");

      fprintf(ofp,
            "============================\n"
            "STACK TRACE OF RUNNING TASKS\n"
            "============================\n\n");

      print_active_stacks(ofp);

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index