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_NIOS2)
78 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
79 						callee_saved.sp),
80 #elif defined(CONFIG_RISCV)
81 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
82 						callee_saved.sp),
83 #elif defined(CONFIG_SPARC)
84 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
85 						callee_saved.o6),
86 #elif defined(CONFIG_ARCH_POSIX)
87 	[THREAD_INFO_OFFSET_T_STACK_PTR] = offsetof(struct k_thread,
88 						callee_saved.thread_status),
89 #elif defined(CONFIG_XTENSA)
90 	/* Xtensa does not store stack pointers inside thread objects.
91 	 * The registers are saved in thread stack where there is
92 	 * no fixed location for this to work. So mark this as
93 	 * unimplemented to avoid the #warning below.
94 	 */
95 	[THREAD_INFO_OFFSET_T_STACK_PTR] = THREAD_INFO_UNIMPLEMENTED,
96 #else
97 	/* Use a special value so that OpenOCD knows that obtaining the stack
98 	 * pointer is not possible on this particular architecture.
99 	 */
100 #warning Please define THREAD_INFO_OFFSET_T_STACK_PTR for this architecture
101 	[THREAD_INFO_OFFSET_T_STACK_PTR] = THREAD_INFO_UNIMPLEMENTED,
102 #endif
103 	/* Version 0 ends */
104 
105 	[THREAD_INFO_OFFSET_T_NAME] = offsetof(struct k_thread, name),
106 	[THREAD_INFO_OFFSET_T_ARCH] = offsetof(struct k_thread, arch),
107 #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) && defined(CONFIG_ARM)
108 	[THREAD_INFO_OFFSET_T_PREEMPT_FLOAT] = offsetof(struct _thread_arch,
109 						    preempt_float),
110 	[THREAD_INFO_OFFSET_T_COOP_FLOAT] = THREAD_INFO_UNIMPLEMENTED,
111 #elif defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) && defined(CONFIG_ARM64)
112 	[THREAD_INFO_OFFSET_T_PREEMPT_FLOAT] = offsetof(struct _thread_arch,
113 							saved_fp_context),
114 	[THREAD_INFO_OFFSET_T_COOP_FLOAT] = THREAD_INFO_UNIMPLEMENTED,
115 #elif defined(CONFIG_FPU) && defined(CONFIG_X86)
116 #if defined(CONFIG_X86_64)
117 	[THREAD_INFO_OFFSET_T_PREEMPT_FLOAT] = offsetof(struct _thread_arch,
118 							sse),
119 #else
120 	[THREAD_INFO_OFFSET_T_PREEMPT_FLOAT] = offsetof(struct _thread_arch,
121 						    preempFloatReg),
122 #endif
123 	[THREAD_INFO_OFFSET_T_COOP_FLOAT] = THREAD_INFO_UNIMPLEMENTED,
124 #else
125 	[THREAD_INFO_OFFSET_T_PREEMPT_FLOAT] = THREAD_INFO_UNIMPLEMENTED,
126 	[THREAD_INFO_OFFSET_T_COOP_FLOAT] = THREAD_INFO_UNIMPLEMENTED,
127 #endif
128 	/* Version is still 1, but existence of following elements must be
129 	 * checked with _kernel_thread_info_num_offsets.
130 	 */
131 #ifdef CONFIG_ARM_STORE_EXC_RETURN
132 	/* ARM overwrites the LSB of the Link Register on the stack when
133 	 * this option is enabled. If this offset is not THREAD_INFO_UNIMPLEMENTED
134 	 * then the LSB needs to be restored from mode_exc_return.
135 	 */
136 	[THREAD_INFO_OFFSET_T_ARM_EXC_RETURN] = offsetof(struct _thread_arch,
137 							 mode_exc_return),
138 #else
139 	[THREAD_INFO_OFFSET_T_ARM_EXC_RETURN] = THREAD_INFO_UNIMPLEMENTED,
140 #endif /* CONFIG_ARM_STORE_EXC_RETURN */
141 #if defined(CONFIG_ARC)
142 	[THREAD_INFO_OFFSET_T_ARC_RELINQUISH_CAUSE] = offsetof(struct _thread_arch,
143 						relinquish_cause),
144 #else
145 	[THREAD_INFO_OFFSET_T_ARC_RELINQUISH_CAUSE] = THREAD_INFO_UNIMPLEMENTED,
146 #endif /* CONFIG_ARC */
147 };
148 
149 extern const size_t __attribute__((alias("_kernel_thread_info_offsets")))
150 		_kernel_openocd_offsets;
151 
152 __attribute__((used, section(".dbg_thread_info")))
153 const size_t _kernel_thread_info_num_offsets = ARRAY_SIZE(_kernel_thread_info_offsets);
154 extern const size_t __attribute__((alias("_kernel_thread_info_num_offsets")))
155 		_kernel_openocd_num_offsets;
156 
157 __attribute__((used, section(".dbg_thread_info")))
158 const uint8_t _kernel_thread_info_size_t_size = (uint8_t)sizeof(size_t);
159 extern const uint8_t __attribute__((alias("_kernel_thread_info_size_t_size")))
160 		_kernel_openocd_size_t_size;
161