zephyr/arch/riscv/core/coredump.c

138 lines
3.0 KiB
C

/*
* Copyright (c) 2021 Facebook, Inc. and its affiliates
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <zephyr/kernel.h>
#include <zephyr/debug/coredump.h>
#ifndef CONFIG_64BIT
#define ARCH_HDR_VER 1
#else
#define ARCH_HDR_VER 2
#endif
struct riscv_arch_block {
#ifdef CONFIG_64BIT
struct {
uint64_t ra;
uint64_t tp;
uint64_t t0;
uint64_t t1;
uint64_t t2;
uint64_t a0;
uint64_t a1;
uint64_t a2;
uint64_t a3;
uint64_t a4;
uint64_t a5;
uint64_t a6;
uint64_t a7;
uint64_t t3;
uint64_t t4;
uint64_t t5;
uint64_t t6;
uint64_t pc;
} r;
#else /* !CONFIG_64BIT */
struct {
uint32_t ra;
uint32_t tp;
uint32_t t0;
uint32_t t1;
uint32_t t2;
uint32_t a0;
uint32_t a1;
uint32_t a2;
uint32_t a3;
uint32_t a4;
uint32_t a5;
#if !defined(CONFIG_RISCV_ISA_RV32E)
uint32_t a6;
uint32_t a7;
uint32_t t3;
uint32_t t4;
uint32_t t5;
uint32_t t6;
#endif /* !CONFIG_RISCV_ISA_RV32E */
uint32_t pc;
} r;
#endif /* CONFIG_64BIT */
} __packed;
/*
* This might be too large for stack space if defined
* inside function. So do it here.
*/
static struct riscv_arch_block arch_blk;
void arch_coredump_info_dump(const struct arch_esf *esf)
{
struct coredump_arch_hdr_t hdr = {
.id = COREDUMP_ARCH_HDR_ID,
.hdr_version = ARCH_HDR_VER,
.num_bytes = sizeof(arch_blk),
};
/* Nothing to process */
if (esf == NULL) {
return;
}
(void)memset(&arch_blk, 0, sizeof(arch_blk));
/*
* 33 registers expected by GDB. Not all are in ESF but the GDB stub will need
* to send all 33 as one packet. The stub will need to send undefined for
* registers not presented in coredump.
*/
arch_blk.r.ra = esf->ra;
arch_blk.r.t0 = esf->t0;
arch_blk.r.t1 = esf->t1;
arch_blk.r.t2 = esf->t2;
arch_blk.r.a0 = esf->a0;
arch_blk.r.a1 = esf->a1;
arch_blk.r.a2 = esf->a2;
arch_blk.r.a3 = esf->a3;
arch_blk.r.a4 = esf->a4;
arch_blk.r.a5 = esf->a5;
#if !defined(CONFIG_RISCV_ISA_RV32E)
arch_blk.r.t3 = esf->t3;
arch_blk.r.t4 = esf->t4;
arch_blk.r.t5 = esf->t5;
arch_blk.r.t6 = esf->t6;
arch_blk.r.a6 = esf->a6;
arch_blk.r.a7 = esf->a7;
#endif /* !CONFIG_RISCV_ISA_RV32E */
arch_blk.r.pc = esf->mepc;
/* Send for output */
coredump_buffer_output((uint8_t *)&hdr, sizeof(hdr));
coredump_buffer_output((uint8_t *)&arch_blk, sizeof(arch_blk));
}
uint16_t arch_coredump_tgt_code_get(void)
{
return COREDUMP_TGT_RISC_V;
}
#if defined(CONFIG_DEBUG_COREDUMP_DUMP_THREAD_PRIV_STACK)
void arch_coredump_priv_stack_dump(struct k_thread *thread)
{
uintptr_t start_addr, end_addr;
/* See: zephyr/include/zephyr/arch/riscv/arch.h */
if (IS_ENABLED(CONFIG_PMP_POWER_OF_TWO_ALIGNMENT)) {
start_addr = thread->arch.priv_stack_start + Z_RISCV_STACK_GUARD_SIZE;
} else {
start_addr = thread->stack_info.start - CONFIG_PRIVILEGED_STACK_SIZE;
}
end_addr = Z_STACK_PTR_ALIGN(thread->arch.priv_stack_start + K_KERNEL_STACK_RESERVED +
CONFIG_PRIVILEGED_STACK_SIZE);
coredump_memory_dump(start_addr, end_addr);
}
#endif /* CONFIG_DEBUG_COREDUMP_DUMP_THREAD_PRIV_STACK */