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

kl_dump_arm.c

/* This file is part of libklib.
 * A library which provides access to Linux system kernel dumps.
 * This file provides architecture dependent support to ARM/XScale
 * system.
 * 
 * This file is ported from kl_dump_i386.c 
 * by Fleming Feng (fleming.feng@intel.com)  
 *
 * Copyright (C)1999, 2005 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C)2003 Intel Corp. All rights reserved.

 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version. See the file COPYING for more
 * information.
 */
#include <klib.h>

static int kl_write_dha_arm(void *);
uint32_t kl_start_physaddr = 0x0;

/* 
 * kl_get_start_physaddr()
 */
uint32_t kl_get_start_physaddr()
{

      kl_dump_header_arm_t dha;
      
      if(kl_get_dump_header_arm(&dha) != 0)
            return 0xffffffff;
      
      return(KL_GET_UINT32(&(dha.physaddr_start)));
      
}

/*
 * kl_get_dump_header_arm()
 */
int
kl_get_dump_header_arm(kl_dump_header_arm_t *dha)
{
      kl_dump_header_t dh;

      if (CORE_IS_KMEM) {
            KL_ERROR = KLE_ACTIVE;
            return(1);
      }

      kl_get_dump_header(&dh);      

      if (lseek(MIP->core_fd, dh.header_size, SEEK_SET) < 0) {
            KL_ERROR = KLE_INVALID_LSEEK;
            return(1);
      }

      if (read(MIP->core_fd, (char *)dha, sizeof(kl_dump_header_arm_t)) != 
          sizeof(kl_dump_header_arm_t)) {
                  KL_ERROR = KLE_INVALID_READ;
                  return(1);
      }

      if (KL_GET_UINT64(&dha->magic_number) != KL_DUMP_MAGIC_NUMBER_ARM) {
            KL_ERROR = KLE_INVALID_DUMP_MAGIC;
            return(1);
      }

      return(0);
}

/*
 * kl_dumpesp_arm()
 */
kaddr_t
kl_dumpesp_arm(kaddr_t tsk)
{
      kl_dump_header_arm_t* dha = NULL;
      kaddr_t addr = (kaddr_t)NULL;
      int i;

      dha = kl_alloc_block(sizeof(kl_dump_header_arm_t), K_TEMP);
      if (dha == NULL) {
            KL_ERROR = KLE_NO_MEMORY;
            return addr;
      }

      if (kl_get_dump_header_arm(dha)) {
            kl_free_block(dha);
            return addr;
      }

      for (i = 0; i < KL_GET_UINT32(&(dha->smp_num_cpus)); i++) {
            if ( tsk == (kaddr_t)(KL_GET_UINT32(&(dha->smp_current_task[i])))){
                  addr = (unsigned long)
                         (KL_GET_UINT32(&(dha->smp_regs[i].dha_ARM_regs.ARM_sp)));
                  break;
            }
      }
      kl_free_block(dha);

      return addr;      
}

/*
 * kl_dumpeip_arm()
 */
kaddr_t
kl_dumpeip_arm(kaddr_t tsk)
{
      kl_dump_header_arm_t* dha = NULL;
      kaddr_t addr = (kaddr_t)NULL;
      int i;

      dha = kl_alloc_block(sizeof(kl_dump_header_arm_t), K_TEMP);
      if (dha == NULL) {
            KL_ERROR = KLE_NO_MEMORY;
            return addr;
      }

      if (kl_get_dump_header_arm(dha)) {
            kl_free_block(dha);
            return addr;
      }

      for (i = 0; i < KL_GET_UINT32(&(dha->smp_num_cpus)); i++) {
            if (tsk == (kaddr_t)(KL_GET_UINT32(&(dha->smp_current_task[i])))){
                  addr = (unsigned long)
                         (KL_GET_UINT32(&(dha->smp_regs[i].dha_ARM_regs.ARM_pc)));
                  break;
            }
      }
      kl_free_block(dha);

      return addr;
}

/*
 * kl_smp_dumptask_arm()
 */
kaddr_t
kl_smp_dumptask_arm(kaddr_t tsk)
{
      kl_dump_header_arm_t* dha = NULL;
      int i;

      dha = kl_alloc_block(sizeof(kl_dump_header_arm_t), K_TEMP);
      if (dha == NULL) {
            KL_ERROR = KLE_NO_MEMORY;
            return (1);
      }

      if (kl_get_dump_header_arm(dha)) {
            kl_free_block(dha);
            return((kaddr_t)NULL);
      }
      
      for (i = 0; i < KL_GET_UINT32(&(dha->smp_num_cpus)); i++) {
            if (tsk == (kaddr_t)(KL_GET_UINT32(&(dha->smp_current_task[i])))){
                  kl_free_block(dha);
                  return (1);
            }
      }
      kl_free_block(dha);

      return (0); 
}

/*
 * kl_set_dumparch_arm()
 */
int
kl_set_dumparch_arm(void)
{
      KLP->dump->arch.pageoffset = KL_PAGE_OFFSET_ARM;
      KLP->dump->arch.kstacksize = KL_KSTACK_SIZE_ARM;
      KLP->dump->arch.pageshift = KL_PAGE_SHIFT_ARM;
      KLP->dump->arch.pagesize = KL_PAGE_SIZE_ARM;
      KLP->dump->arch.pagemask = KL_PAGE_MASK_ARM;
      KLP->dump->arch.pgdshift = KL_PGDIR_SHIFT_ARM;
      KLP->dump->arch.pgdsize = KL_PGDIR_SIZE_ARM;
      KLP->dump->arch.pgdmask = KL_PGDIR_MASK_ARM;
      KLP->dump->arch.pmdshift = KL_PMD_SHIFT_ARM;
      KLP->dump->arch.pmdsize = KL_PMD_SIZE_ARM;
      KLP->dump->arch.pmdmask = KL_PMD_MASK_ARM;
      KLP->dump->arch.ptrsperpgd = KL_PTRS_PER_PGD_ARM;
      KLP->dump->arch.ptrsperpmd = KL_PTRS_PER_PMD_ARM;
      KLP->dump->arch.ptrsperpte = KL_PTRS_PER_PTE_ARM;
      KLP->dump->arch.kernelstack = kl_kernelstack_arm;
      KLP->dump->arch.mmap_virtop = kl_mmap_virtop_arm;
      KLP->dump->arch.init_virtop = kl_init_virtop_arm;
      KLP->dump->arch.virtop = kl_virtop_arm;
      KLP->dump->arch.fix_vaddr = kl_fix_vaddr_arm;
      KLP->dump->arch.dha_size = sizeof(kl_dump_header_arm_t);
      KLP->dump->arch.write_dha = kl_write_dha_arm;
      return(0);
}


/*
 * kl_write_dump_header_arm()
 */
static int
kl_write_dha_arm(void *buf)
{
      kl_dump_header_arm_t dha;

      memset(&dha, 0, sizeof(dha));

      dha.magic_number = KL_DUMP_MAGIC_NUMBER_ARM;
      dha.version = KL_DUMP_VERSION_NUMBER_ARM;
      dha.header_size = sizeof(dha);

      memcpy(buf, &dha, dha.header_size);

      return(0);
}

/*
 * kl_get_target_byteorder()
 */
int
kl_get_target_byteorder(char* dump)
{

      int fd;
      unsigned long long magic_number;

      if(strcmp(dump, "/dev/mem")==0){
            /* This is not for live dump */
            return 0;
      }
      else{
            if((fd = open(dump, 0)) == -1){
                  /* can not open dump file and get byteorder info */
                  return 0;
            }
            if(read(fd, &magic_number, sizeof(unsigned long long)) !=
               sizeof(unsigned long long)){
                  close(fd);
                  return 0;
            }
            close(fd);
            if(magic_number == KL_DUMP_MAGIC_NUMBER || 
               magic_number == KL_DUMP_REVERSE_MAGIC_NUMBER){
                  if(magic_number == KL_DUMP_MAGIC_NUMBER){
                        return KLP->host->byteorder;
                  }
                  else{
                        /* magic_number == 
                           KL_DUMP_REVERSE_MAGIC_NUMBER */
                        if(KLP->host->byteorder == KL_LITTLE_ENDIAN)
                              return KL_BIG_ENDIAN;
                        else if(KLP->host->byteorder == KL_BIG_ENDIAN)
                              return KL_LITTLE_ENDIAN;
                        else
                              return 0;
                  }
            }
      }

      return 0;

}


Generated by  Doxygen 1.6.0   Back to index