1 /*
2 * Copyright © 2014 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including
13 * the next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "libhsakmt.h"
27 #include "linux/kfd_ioctl.h"
28 #include <stdlib.h>
29 #include <string.h>
30
31 static bool *is_device_debugged;
32 int debug_get_reg_status(uint32_t node_id, bool *is_debugged);
33
init_device_debugging_memory(unsigned int NumNodes)34 HSAKMT_STATUS init_device_debugging_memory(unsigned int NumNodes)
35 {
36 unsigned int i;
37
38 is_device_debugged = malloc(NumNodes * sizeof(bool));
39 if (!is_device_debugged)
40 return HSAKMT_STATUS_NO_MEMORY;
41
42 for (i = 0; i < NumNodes; i++)
43 is_device_debugged[i] = false;
44
45 return HSAKMT_STATUS_SUCCESS;
46 }
47
destroy_device_debugging_memory(void)48 void destroy_device_debugging_memory(void)
49 {
50 if (is_device_debugged) {
51 free(is_device_debugged);
52 is_device_debugged = NULL;
53 }
54 }
55
hsaKmtDbgRegister(HSAuint32 NodeId)56 HSAKMT_STATUS HSAKMTAPI hsaKmtDbgRegister(HSAuint32 NodeId)
57 {
58 HSAKMT_STATUS result;
59 uint32_t gpu_id;
60
61 CHECK_KFD_OPEN();
62
63 if (!is_device_debugged)
64 return HSAKMT_STATUS_NO_MEMORY;
65
66 result = validate_nodeid(NodeId, &gpu_id);
67 if (result != HSAKMT_STATUS_SUCCESS)
68 return result;
69
70 struct kfd_ioctl_dbg_register_args args = {0};
71
72 args.gpu_id = gpu_id;
73
74 long err = kmtIoctl(kfd_fd, AMDKFD_IOC_DBG_REGISTER, &args);
75
76 if (err == 0)
77 result = HSAKMT_STATUS_SUCCESS;
78 else
79 result = HSAKMT_STATUS_ERROR;
80
81 return result;
82 }
83
hsaKmtDbgUnregister(HSAuint32 NodeId)84 HSAKMT_STATUS HSAKMTAPI hsaKmtDbgUnregister(HSAuint32 NodeId)
85 {
86 uint32_t gpu_id;
87 HSAKMT_STATUS result;
88
89 CHECK_KFD_OPEN();
90
91 if (!is_device_debugged)
92 return HSAKMT_STATUS_NO_MEMORY;
93
94 result = validate_nodeid(NodeId, &gpu_id);
95 if (result != HSAKMT_STATUS_SUCCESS)
96 return result;
97
98 struct kfd_ioctl_dbg_unregister_args args = {0};
99
100 args.gpu_id = gpu_id;
101 long err = kmtIoctl(kfd_fd, AMDKFD_IOC_DBG_UNREGISTER, &args);
102
103 if (err)
104 return HSAKMT_STATUS_ERROR;
105
106 return HSAKMT_STATUS_SUCCESS;
107 }
108
hsaKmtDbgWavefrontControl(HSAuint32 NodeId,HSA_DBG_WAVEOP Operand,HSA_DBG_WAVEMODE Mode,HSAuint32 TrapId,HsaDbgWaveMessage * DbgWaveMsgRing)109 HSAKMT_STATUS HSAKMTAPI hsaKmtDbgWavefrontControl(HSAuint32 NodeId,
110 HSA_DBG_WAVEOP Operand,
111 HSA_DBG_WAVEMODE Mode,
112 HSAuint32 TrapId,
113 HsaDbgWaveMessage *DbgWaveMsgRing)
114 {
115 HSAKMT_STATUS result;
116 uint32_t gpu_id;
117
118 struct kfd_ioctl_dbg_wave_control_args *args;
119
120 CHECK_KFD_OPEN();
121
122 result = validate_nodeid(NodeId, &gpu_id);
123 if (result != HSAKMT_STATUS_SUCCESS)
124 return result;
125
126
127 /* Determine Size of the ioctl buffer */
128 uint32_t buff_size = sizeof(Operand) + sizeof(Mode) + sizeof(TrapId) +
129 sizeof(DbgWaveMsgRing->DbgWaveMsg) +
130 sizeof(DbgWaveMsgRing->MemoryVA) + sizeof(*args);
131
132 args = (struct kfd_ioctl_dbg_wave_control_args *)malloc(buff_size);
133 if (!args)
134 return HSAKMT_STATUS_ERROR;
135
136 memset(args, 0, buff_size);
137
138 args->gpu_id = gpu_id;
139 args->buf_size_in_bytes = buff_size;
140
141 /* increment pointer to the start of the non fixed part */
142 unsigned char *run_ptr = (unsigned char *)args + sizeof(*args);
143
144 /* save variable content pointer for kfd */
145 args->content_ptr = (uint64_t)run_ptr;
146
147 /* insert items, and increment pointer accordingly */
148 *((HSA_DBG_WAVEOP *)run_ptr) = Operand;
149 run_ptr += sizeof(Operand);
150
151 *((HSA_DBG_WAVEMODE *)run_ptr) = Mode;
152 run_ptr += sizeof(Mode);
153
154 *((HSAuint32 *)run_ptr) = TrapId;
155 run_ptr += sizeof(TrapId);
156
157 *((HsaDbgWaveMessageAMD *)run_ptr) = DbgWaveMsgRing->DbgWaveMsg;
158 run_ptr += sizeof(DbgWaveMsgRing->DbgWaveMsg);
159
160 *((void **)run_ptr) = DbgWaveMsgRing->MemoryVA;
161 run_ptr += sizeof(DbgWaveMsgRing->MemoryVA);
162
163 /* send to kernel */
164 long err = kmtIoctl(kfd_fd, AMDKFD_IOC_DBG_WAVE_CONTROL, args);
165
166 free(args);
167
168 if (err)
169 return HSAKMT_STATUS_ERROR;
170
171 return HSAKMT_STATUS_SUCCESS;
172 }
173
hsaKmtDbgAddressWatch(HSAuint32 NodeId,HSAuint32 NumWatchPoints,HSA_DBG_WATCH_MODE WatchMode[],void * WatchAddress[],HSAuint64 WatchMask[],HsaEvent * WatchEvent[])174 HSAKMT_STATUS HSAKMTAPI hsaKmtDbgAddressWatch(HSAuint32 NodeId,
175 HSAuint32 NumWatchPoints,
176 HSA_DBG_WATCH_MODE WatchMode[],
177 void *WatchAddress[],
178 HSAuint64 WatchMask[],
179 HsaEvent *WatchEvent[])
180 {
181 HSAKMT_STATUS result;
182 uint32_t gpu_id;
183
184 /* determine the size of the watch mask and event buffers
185 * the value is NULL if and only if no vector data should be attached
186 */
187 uint32_t watch_mask_items = WatchMask[0] > 0 ? NumWatchPoints:1;
188 uint32_t watch_event_items = WatchEvent != NULL ? NumWatchPoints:0;
189
190 struct kfd_ioctl_dbg_address_watch_args *args;
191 HSAuint32 i = 0;
192
193 CHECK_KFD_OPEN();
194
195 result = validate_nodeid(NodeId, &gpu_id);
196 if (result != HSAKMT_STATUS_SUCCESS)
197 return result;
198
199 if (NumWatchPoints > MAX_ALLOWED_NUM_POINTS)
200 return HSAKMT_STATUS_INVALID_PARAMETER;
201
202 /* Size and structure of the ioctl buffer is dynamic in this case
203 * Here we calculate the buff size.
204 */
205 uint32_t buff_size = sizeof(NumWatchPoints) +
206 (sizeof(WatchMode[0]) + sizeof(WatchAddress[0])) *
207 NumWatchPoints +
208 watch_mask_items * sizeof(HSAuint64) +
209 watch_event_items * sizeof(HsaEvent *) + sizeof(*args);
210
211 args = (struct kfd_ioctl_dbg_address_watch_args *) malloc(buff_size);
212 if (!args)
213 return HSAKMT_STATUS_ERROR;
214
215 memset(args, 0, buff_size);
216
217 args->gpu_id = gpu_id;
218 args->buf_size_in_bytes = buff_size;
219
220
221 /* increment pointer to the start of the non fixed part */
222 unsigned char *run_ptr = (unsigned char *)args + sizeof(*args);
223
224 /* save variable content pointer for kfd */
225 args->content_ptr = (uint64_t)run_ptr;
226 /* insert items, and increment pointer accordingly */
227
228 *((HSAuint32 *)run_ptr) = NumWatchPoints;
229 run_ptr += sizeof(NumWatchPoints);
230
231 for (i = 0; i < NumWatchPoints; i++) {
232 *((HSA_DBG_WATCH_MODE *)run_ptr) = WatchMode[i];
233 run_ptr += sizeof(WatchMode[i]);
234 }
235
236 for (i = 0; i < NumWatchPoints; i++) {
237 *((void **)run_ptr) = WatchAddress[i];
238 run_ptr += sizeof(WatchAddress[i]);
239 }
240
241 for (i = 0; i < watch_mask_items; i++) {
242 *((HSAuint64 *)run_ptr) = WatchMask[i];
243 run_ptr += sizeof(WatchMask[i]);
244 }
245
246 for (i = 0; i < watch_event_items; i++) {
247 *((HsaEvent **)run_ptr) = WatchEvent[i];
248 run_ptr += sizeof(WatchEvent[i]);
249 }
250
251 /* send to kernel */
252 long err = kmtIoctl(kfd_fd, AMDKFD_IOC_DBG_ADDRESS_WATCH, args);
253
254 free(args);
255
256 if (err)
257 return HSAKMT_STATUS_ERROR;
258 return HSAKMT_STATUS_SUCCESS;
259 }
260
debug_get_reg_status(uint32_t node_id,bool * is_debugged)261 int debug_get_reg_status(uint32_t node_id, bool *is_debugged)
262 {
263 *is_debugged = NULL;
264 if (!is_device_debugged)
265 return -1;
266
267 *is_debugged = is_device_debugged[node_id];
268 return 0;
269 }
270