/* * Copyright (c) 2021 Facebook, Inc. and its affiliates * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #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 */