1 /*
2  * Copyright (c) 2020 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/debug/coredump.h>
10 
11 #define ARCH_HDR_VER			1
12 
13 struct x86_64_arch_block {
14 	uint64_t	vector;
15 	uint64_t	code;
16 
17 	struct {
18 		uint64_t	rax;
19 		uint64_t	rcx;
20 		uint64_t	rdx;
21 		uint64_t	rsi;
22 		uint64_t	rdi;
23 		uint64_t	rsp;
24 		uint64_t	r8;
25 		uint64_t	r9;
26 		uint64_t	r10;
27 		uint64_t	r11;
28 		uint64_t	rip;
29 		uint64_t	eflags;
30 		uint64_t	cs;
31 		uint64_t	ss;
32 		uint64_t	rbp;
33 
34 #ifdef CONFIG_EXCEPTION_DEBUG
35 		uint64_t	rbx;
36 		uint64_t	r12;
37 		uint64_t	r13;
38 		uint64_t	r14;
39 		uint64_t	r15;
40 #endif
41 	} r;
42 } __packed;
43 
44 /*
45  * Register block takes up too much stack space
46  * if defined within function. So define it here.
47  */
48 static struct x86_64_arch_block arch_blk;
49 
arch_coredump_info_dump(const struct arch_esf * esf)50 void arch_coredump_info_dump(const struct arch_esf *esf)
51 {
52 	struct coredump_arch_hdr_t hdr = {
53 		.id = COREDUMP_ARCH_HDR_ID,
54 		.hdr_version = ARCH_HDR_VER,
55 		.num_bytes = sizeof(arch_blk),
56 	};
57 
58 	/* Nothing to process */
59 	if (esf == NULL) {
60 		return;
61 	}
62 
63 	(void)memset(&arch_blk, 0, sizeof(arch_blk));
64 
65 	arch_blk.vector = esf->vector;
66 	arch_blk.code = esf->code;
67 
68 	/*
69 	 * 34 registers expected by GDB.
70 	 * Not all are in ESF but the GDB stub
71 	 * will need to send all 34 as one packet.
72 	 * The stub will need to send undefined
73 	 * for registers not presented in coredump.
74 	 */
75 	arch_blk.r.rax = esf->rax;
76 	arch_blk.r.rcx = esf->rcx;
77 	arch_blk.r.rdx = esf->rdx;
78 	arch_blk.r.rsi = esf->rsi;
79 	arch_blk.r.rdi = esf->rdi;
80 	arch_blk.r.rsp = esf->rsp;
81 	arch_blk.r.rip = esf->rip;
82 	arch_blk.r.r8  = esf->r8;
83 	arch_blk.r.r9  = esf->r9;
84 	arch_blk.r.r10 = esf->r10;
85 	arch_blk.r.r11 = esf->r11;
86 
87 	arch_blk.r.eflags = esf->rflags;
88 	arch_blk.r.cs = esf->cs & 0xFFFFU;
89 	arch_blk.r.ss = esf->ss;
90 
91 	arch_blk.r.rbp = esf->rbp;
92 
93 #ifdef CONFIG_EXCEPTION_DEBUG
94 	arch_blk.r.rbx = esf->rbx;
95 	arch_blk.r.r12 = esf->r12;
96 	arch_blk.r.r13 = esf->r13;
97 	arch_blk.r.r14 = esf->r14;
98 	arch_blk.r.r15 = esf->r15;
99 #endif
100 
101 	/* Send for output */
102 	coredump_buffer_output((uint8_t *)&hdr, sizeof(hdr));
103 	coredump_buffer_output((uint8_t *)&arch_blk, sizeof(arch_blk));
104 }
105 
arch_coredump_tgt_code_get(void)106 uint16_t arch_coredump_tgt_code_get(void)
107 {
108 	return COREDUMP_TGT_X86_64;
109 }
110 
111 #if defined(CONFIG_DEBUG_COREDUMP_DUMP_THREAD_PRIV_STACK)
arch_coredump_priv_stack_dump(struct k_thread * thread)112 void arch_coredump_priv_stack_dump(struct k_thread *thread)
113 {
114 	struct z_x86_thread_stack_header *hdr_stack_obj;
115 	uintptr_t start_addr, end_addr;
116 
117 #if defined(CONFIG_THREAD_STACK_MEM_MAPPED)
118 	hdr_stack_obj = (struct z_x86_thread_stack_header *)thread->stack_info.mapped.addr;
119 #else
120 	hdr_stack_obj = (struct z_x86_thread_stack_header *)thread->stack_obj;
121 #endif /* CONFIG_THREAD_STACK_MEM_MAPPED) */
122 
123 	start_addr = (uintptr_t)&hdr_stack_obj->privilege_stack[0];
124 	end_addr = start_addr + sizeof(hdr_stack_obj->privilege_stack);
125 
126 	coredump_memory_dump(start_addr, end_addr);
127 }
128 #endif /* CONFIG_DEBUG_COREDUMP_DUMP_THREAD_PRIV_STACK */
129