1 /*
2  * Copyright (c) 2017 Intel Corporation
3  * Copyright 2023 NXP
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/kernel.h>
9 
10 #define THREAD_INFO_UNIMPLEMENTED	0xffffffff
11 
12 enum {
13 	THREAD_INFO_OFFSET_VERSION,
14 	THREAD_INFO_OFFSET_K_CURR_THREAD,
15 	THREAD_INFO_OFFSET_K_THREADS,
16 	THREAD_INFO_OFFSET_T_ENTRY,
17 	THREAD_INFO_OFFSET_T_NEXT_THREAD,
18 	THREAD_INFO_OFFSET_T_STATE,
19 	THREAD_INFO_OFFSET_T_USER_OPTIONS,
20 	THREAD_INFO_OFFSET_T_PRIO,
21 	THREAD_INFO_OFFSET_T_STACK_PTR,
22 	THREAD_INFO_OFFSET_T_NAME,
23 	THREAD_INFO_OFFSET_T_ARCH,
24 	THREAD_INFO_OFFSET_T_PREEMPT_FLOAT,
25 	THREAD_INFO_OFFSET_T_COOP_FLOAT,
26 	THREAD_INFO_OFFSET_T_ARM_EXC_RETURN,
27 	THREAD_INFO_OFFSET_T_ARC_RELINQUISH_CAUSE,
28 };
29 
30 #if CONFIG_MP_MAX_NUM_CPUS > 1
31 #error "This code doesn't work properly with multiple CPUs enabled"
32 #endif
33 
34 /* Forward-compatibility notes: 1) Only append items to this table; otherwise
35  * debugger plugin versions that expect fewer items will read garbage values.
36  * 2) Avoid incompatible changes that affect the interpretation of existing
37  * items. But if you have to do them, increment THREAD_INFO_OFFSET_VERSION
38  * and submit a patch for debugger plugins to deal with both the old and new
39  * scheme.
40  * Only version 1 is backward compatible to version 0.
41  */
42 __attribute__((used, section(".dbg_thread_info")))
43 const size_t _kernel_thread_info_offsets[] = {
44 	/* Version 0 starts */
45 	[THREAD_INFO_OFFSET_VERSION] = 1,
46 	[THREAD_INFO_OFFSET_K_CURR_THREAD] = offsetof(struct _cpu, current),
47 	[THREAD_INFO_OFFSET_K_THREADS] = offsetof(struct z_kernel, threads),
48 	[THREAD_INFO_OFFSET_T_ENTRY] = offsetof(struct k_thread, entry),
49 	[THREAD_INFO_OFFSET_T_NEXT_THREAD] = offsetof(struct k_thread,
50 						      next_thread),
51 	[THREAD_INFO_OFFSET_T_STATE] = offsetof(struct _thread_base,
52 						thread_state),
53 	[THREAD_INFO_OFFSET_T_USER_OPTIONS] = offsetof(struct _thread_base,
54 						   user_options),
55 	[THREAD_INFO_OFFSET_T_PRIO] = offsetof(struct _thread_base, prio),
56 #if defined(CONFIG_ARM64)
57 	/* We are assuming that the SP of interest is SP_EL1 */
58 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
59 						callee_saved.sp_elx),
60 #elif defined(CONFIG_ARM)
61 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
62 						callee_saved.psp),
63 #elif defined(CONFIG_ARC)
64 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
65 						callee_saved.sp),
66 #elif defined(CONFIG_X86)
67 #if defined(CONFIG_X86_64)
68 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
69 						callee_saved.rsp),
70 #else
71 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
72 						callee_saved.esp),
73 #endif
74 #elif defined(CONFIG_MIPS)
75 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
76 						callee_saved.sp),
77 #elif defined(CONFIG_RX)
78 	[THREAD_INFO_OFFSET_T_STACK_PTR] = THREAD_INFO_UNIMPLEMENTED,
79 #elif defined(CONFIG_RISCV)
80 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
81 						callee_saved.sp),
82 #elif defined(CONFIG_SPARC)
83 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
84 						callee_saved.o6),
85 #elif defined(CONFIG_ARCH_POSIX)
86 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
87 						callee_saved.thread_status),
88 #elif defined(CONFIG_XTENSA)
89 	/* Xtensa does not store stack pointers inside thread objects.
90 	 * The registers are saved in thread stack where there is
91 	 * no fixed location for this to work. So mark this as
92 	 * unimplemented to avoid the #warning below.
93 	 */
94 	[THREAD_INFO_OFFSET_T_STACK_PTR] = THREAD_INFO_UNIMPLEMENTED,
95 #elif defined(CONFIG_RX)
96 	/* RX doesn't store *anything* inside thread objects yet */
97 	[THREAD_INFO_OFFSET_T_STACK_PTR] = THREAD_INFO_UNIMPLEMENTED,
98 #else
99 	/* Use a special value so that OpenOCD knows that obtaining the stack
100 	 * pointer is not possible on this particular architecture.
101 	 */
102 #warning Please define THREAD_INFO_OFFSET_T_STACK_PTR for this architecture
103 	[THREAD_INFO_OFFSET_T_STACK_PTR] = THREAD_INFO_UNIMPLEMENTED,
104 #endif
105 	/* Version 0 ends */
106 
107 	[THREAD_INFO_OFFSET_T_NAME] = offsetof(struct k_thread, name),
108 	[THREAD_INFO_OFFSET_T_ARCH] = offsetof(struct k_thread, arch),
109 #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) && defined(CONFIG_ARM)
110 	[THREAD_INFO_OFFSET_T_PREEMPT_FLOAT] = offsetof(struct _thread_arch,
111 						    preempt_float),
112 	[THREAD_INFO_OFFSET_T_COOP_FLOAT] = THREAD_INFO_UNIMPLEMENTED,
113 #elif defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) && defined(CONFIG_ARM64)
114 	[THREAD_INFO_OFFSET_T_PREEMPT_FLOAT] = offsetof(struct _thread_arch,
115 							saved_fp_context),
116 	[THREAD_INFO_OFFSET_T_COOP_FLOAT] = THREAD_INFO_UNIMPLEMENTED,
117 #elif defined(CONFIG_FPU) && defined(CONFIG_X86)
118 #if defined(CONFIG_X86_64)
119 	[THREAD_INFO_OFFSET_T_PREEMPT_FLOAT] = offsetof(struct _thread_arch,
120 							sse),
121 #else
122 	[THREAD_INFO_OFFSET_T_PREEMPT_FLOAT] = offsetof(struct _thread_arch,
123 						    preempFloatReg),
124 #endif
125 	[THREAD_INFO_OFFSET_T_COOP_FLOAT] = THREAD_INFO_UNIMPLEMENTED,
126 #else
127 	[THREAD_INFO_OFFSET_T_PREEMPT_FLOAT] = THREAD_INFO_UNIMPLEMENTED,
128 	[THREAD_INFO_OFFSET_T_COOP_FLOAT] = THREAD_INFO_UNIMPLEMENTED,
129 #endif
130 	/* Version is still 1, but existence of following elements must be
131 	 * checked with _kernel_thread_info_num_offsets.
132 	 */
133 #ifdef CONFIG_ARM_STORE_EXC_RETURN
134 	/* ARM overwrites the LSB of the Link Register on the stack when
135 	 * this option is enabled. If this offset is not THREAD_INFO_UNIMPLEMENTED
136 	 * then the LSB needs to be restored from mode_exc_return.
137 	 */
138 	[THREAD_INFO_OFFSET_T_ARM_EXC_RETURN] = offsetof(struct _thread_arch,
139 							 mode_exc_return),
140 #else
141 	[THREAD_INFO_OFFSET_T_ARM_EXC_RETURN] = THREAD_INFO_UNIMPLEMENTED,
142 #endif /* CONFIG_ARM_STORE_EXC_RETURN */
143 #if defined(CONFIG_ARC)
144 	[THREAD_INFO_OFFSET_T_ARC_RELINQUISH_CAUSE] = offsetof(struct _thread_arch,
145 						relinquish_cause),
146 #else
147 	[THREAD_INFO_OFFSET_T_ARC_RELINQUISH_CAUSE] = THREAD_INFO_UNIMPLEMENTED,
148 #endif /* CONFIG_ARC */
149 };
150 
151 extern const size_t __attribute__((alias("_kernel_thread_info_offsets")))
152 		_kernel_openocd_offsets;
153 
154 __attribute__((used, section(".dbg_thread_info")))
155 const size_t _kernel_thread_info_num_offsets = ARRAY_SIZE(_kernel_thread_info_offsets);
156 extern const size_t __attribute__((alias("_kernel_thread_info_num_offsets")))
157 		_kernel_openocd_num_offsets;
158 
159 __attribute__((used, section(".dbg_thread_info")))
160 const uint8_t _kernel_thread_info_size_t_size = (uint8_t)sizeof(size_t);
161 extern const uint8_t __attribute__((alias("_kernel_thread_info_size_t_size")))
162 		_kernel_openocd_size_t_size;
163