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

kl_dump_ppc64.c

/*
 * $Id: kl_dump_ppc64.c,v 1.2 2005/02/23 01:09:12 tjm Exp $
 *
 * This file is part of libklib.
 * A library which provides access to Linux system kernel dumps.
 *
 * Created by Silicon Graphics, Inc.
 * Contributions by IBM, NEC, and others
 *
 * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
 * Copyright 2000 Junichi Nomura, NEC Solutions <j-nomura@ce.jp.nec.com>
 *
 * 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>
#include <linux/stddef.h>     /* offsetof */

extern kaddr_t kl_mmap_virtop_ppc64(kaddr_t, void *);
static kl_dump_header_ppc64_t arch_hdr;

/*
 * get_dump_header_ppc64()
 */
int 
kl_get_dump_header_ppc64(kl_dump_header_ppc64_t *dha)
{
      kl_dump_header_t dh;
      uint32_t hdr_size, offset, nr_cpus;
      char hdr_buf[KL_DUMP_HEADER_SIZE];

      /* first, make sure this isn't a live system
       */
      if (CORE_IS_KMEM) {
            KL_ERROR = KLE_ACTIVE;
            return(1);
      }

      if (KL_GET_UINT64(&arch_hdr.magic_number) 
            == KL_DUMP_MAGIC_NUMBER_PPC64) {
            /*
             * Already read from the dump file.
             */
            memcpy(dha, &arch_hdr, sizeof(kl_dump_header_ppc64_t));
                return(0);
        }
      /* get the dump header
       */

      kl_get_dump_header(&dh);

      if (lseek(MIP->core_fd, 
            dh.header_size +  offsetof(kl_dump_header_ppc64_t, header_size),
            SEEK_SET) < 0) {
            KL_ERROR = KLE_INVALID_LSEEK;
            return(1);
      }
      if (read(MIP->core_fd, (char *)&hdr_size, sizeof(hdr_size)) !=
            sizeof(hdr_size)) {
            KL_ERROR = KLE_INVALID_READ;
            return(1);
      }
      if (lseek(MIP->core_fd, dh.header_size, SEEK_SET) < 0) {
            KL_ERROR = KLE_INVALID_LSEEK;
            return(1);
      }
      if (read(MIP->core_fd, (char *)&hdr_buf[0], hdr_size) !=
            hdr_size) {
            KL_ERROR = KLE_INVALID_READ;
            return(1);
      }
      /*
       * Though we have KL_NR_CPUS is 128, the header size is different
       * CONFIG_NR_CPUS might be different in the kernel. Hence, need
       * to find out how many CPUs are configured.
       * To do that, calculate the size of pt_regs, task_ptr, stack_addr,
       * and stack_ptr for a single CPU. 
       * CPU_size = sizeof(pt_regs) + sizeof(uint64_t) * 3;
       * NR_CPUS = (header_size - offset of smp_regs[0]) / CPU_size
       */
      offset = offsetof(kl_dump_header_ppc64_t, smp_regs[0]);
      nr_cpus = (hdr_size - offset) / sizeof(struct kl_dump_CPU_info_ppc64);
      
      if (nr_cpus > KL_NR_CPUS) {
            /* Not supported > 128 now. Change KL_NR_CPUS value in 
             * klib.h and kl_dump_ppc64.h */
            KL_ERROR = KLE_INVALID_READ;
            return(1);
      }

      memcpy(&arch_hdr, (void *)&hdr_buf, offset);
      memcpy(&arch_hdr.smp_regs[0], (void *)&hdr_buf[offset],
            nr_cpus * sizeof(struct kl_pt_regs_ppc64));
      offset += nr_cpus * sizeof(struct kl_pt_regs_ppc64);
      memcpy(&arch_hdr.smp_current_task[0], (void *)&hdr_buf[offset],
            nr_cpus * sizeof(arch_hdr.smp_current_task[0]));
      offset += nr_cpus * sizeof(arch_hdr.smp_current_task[0]);
      memcpy(&arch_hdr.stack[0], (void *)&hdr_buf[offset],
                nr_cpus * sizeof(arch_hdr.stack[0]));
        offset += nr_cpus * sizeof(arch_hdr.stack[0]);
      memcpy(&arch_hdr.stack_ptr[0], (void *)&hdr_buf[offset],
                nr_cpus * sizeof(arch_hdr.stack_ptr[0]));

      if (KL_GET_UINT64(&arch_hdr.magic_number) 
            != KL_DUMP_MAGIC_NUMBER_PPC64) {
            KL_ERROR = KLE_INVALID_DUMP_MAGIC;
            return(1);
      }
      memcpy(dha, &arch_hdr, sizeof(kl_dump_header_ppc64_t));
      
      return(0);
}

/*
 * kl_dumpgpr_ppc64()
 */
kaddr_t
kl_dumpgpr_ppc64(kaddr_t tsk)
{
      kl_dump_header_ppc64_t dha;
      int i;

      if (kl_get_dump_header_ppc64(&dha)) {
            return((kaddr_t)NULL);
      }

      for (i = 0; i < KL_GET_UINT32(&dha.smp_num_cpus); i++) {
            if (tsk == (kaddr_t)KL_GET_UINT64(&dha.smp_current_task[i])) {
                  return (kaddr_t)KL_GET_UINT64(&dha.smp_regs[i].gpr[1]);
            }
      }

      return((kaddr_t)NULL);
}

/*
 * kl_dumpnip_ppc64()
 */
kaddr_t
kl_dumpnip_ppc64(kaddr_t tsk)
{
      kl_dump_header_ppc64_t dha;
      int i;

      if (kl_get_dump_header_ppc64(&dha)) {
            return((kaddr_t)NULL);
      }

      for (i = 0; i < KL_GET_UINT32(&dha.smp_num_cpus); i++) {
            if (tsk == (kaddr_t)KL_GET_UINT64(&dha.smp_current_task[i])) {
                  //fprintf(stderr, "kl_dumpnip lr=0x%lx\n", dha.smp_regs[i].link);
                  return (kaddr_t)KL_GET_UINT64(&dha.smp_regs[i].nip);
            }
      }

      return((kaddr_t)NULL);
}

/*
 * kl_smp_dumptask_ppc64()
 */
int
kl_smp_dumptask_ppc64(kaddr_t tsk)
{
      kl_dump_header_ppc64_t dha;
      int i;

      if (kl_get_dump_header_ppc64(&dha)) {
            return((kaddr_t)NULL);
      }

      for (i = 0; i < KL_GET_UINT32(&dha.smp_num_cpus); i++) {
            if (tsk == (kaddr_t)KL_GET_UINT64(&dha.smp_current_task[i]))
                  return (1);
      }
      return (0); 
 }

/*
 *  * kl_write_dump_header_ppc64()
 *   */
static int
kl_write_dha_ppc64(void *buf)
{
      kl_dump_header_ppc64_t dha;

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

      dha.magic_number = KL_DUMP_MAGIC_NUMBER_PPC64;
      dha.version = KL_DUMP_VERSION_NUMBER_PPC64;
      dha.header_size = sizeof(dha);

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

      return(0);
}

/*
 * kl_set_dumparch_ppc64()
 */
int
kl_set_dumparch_ppc64(void)
{
      KLP->dump->arch.pageoffset = KL_PAGE_OFFSET_PPC64;
      KLP->dump->arch.kstacksize = KL_KSTACK_SIZE_PPC64;
      KLP->dump->arch.pageshift = KL_PAGE_SHIFT_PPC64;
      KLP->dump->arch.pagesize = KL_PAGE_SIZE_PPC64;
      KLP->dump->arch.pagemask = KL_PAGE_MASK_PPC64;
      KLP->dump->arch.pgdshift = KL_PGDIR_SHIFT_PPC64;
      KLP->dump->arch.pgdsize = KL_PGDIR_SIZE_PPC64;
      KLP->dump->arch.pgdmask = KL_PGDIR_MASK_PPC64;
      KLP->dump->arch.pmdshift = KL_PMD_SHIFT_PPC64;
      KLP->dump->arch.pmdsize = KL_PMD_SIZE_PPC64;
      KLP->dump->arch.pmdmask = KL_PMD_MASK_PPC64;
      KLP->dump->arch.ptrsperpgd = KL_PTRS_PER_PGD_PPC64;
      KLP->dump->arch.ptrsperpmd = KL_PTRS_PER_PMD_PPC64;
      KLP->dump->arch.ptrsperpte = KL_PTRS_PER_PTE_PPC64;
      KLP->dump->arch.kernelstack = kl_kernelstack_ppc64;
      KLP->dump->arch.mmap_virtop = kl_mmap_virtop_ppc64;
      KLP->dump->arch.fix_vaddr = kl_fix_vaddr_ppc64;
      KLP->dump->arch.dha_size = sizeof(kl_dump_header_ppc64_t);
      KLP->dump->arch.write_dha = kl_write_dha_ppc64;
      return(0);
}

Generated by  Doxygen 1.6.0   Back to index