Rev 2885 | Rev 2887 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2885 | Rev 2886 | ||
---|---|---|---|
Line 16... | Line 16... | ||
16 | #include <syscall/copy.h> |
16 | #include <syscall/copy.h> |
17 | #include <udebug/udebug.h> |
17 | #include <udebug/udebug.h> |
18 | #include <udebug/udebug_ipc.h> |
18 | #include <udebug/udebug_ipc.h> |
19 | 19 | ||
20 | /** |
20 | /** |
21 | * Get a phone's callee task id. |
- | |
22 | * |
- | |
23 | * This will return the id of the task to which the phone |
- | |
24 | * is connected. |
- | |
25 | * |
- | |
26 | * Interrupts must be already disabled. |
- | |
27 | */ |
- | |
28 | static task_id_t get_callee_task_id(phone_t *phone) |
- | |
29 | { |
- | |
30 | answerbox_t *box; |
- | |
31 | task_id_t taskid; |
- | |
32 | - | ||
33 | spinlock_lock(&phone->lock); |
- | |
34 | if (phone->state != IPC_PHONE_CONNECTED) { |
- | |
35 | spinlock_unlock(&phone->lock); |
- | |
36 | return NULL; |
- | |
37 | } |
- | |
38 | - | ||
39 | box = phone->callee; |
- | |
40 | - | ||
41 | spinlock_lock(&box->lock); |
- | |
42 | taskid = box->task->taskid; |
- | |
43 | spinlock_unlock(&box->lock); |
- | |
44 | spinlock_unlock(&phone->lock); |
- | |
45 | - | ||
46 | return taskid; |
- | |
47 | } |
- | |
48 | - | ||
49 | /** |
- | |
50 | * Prepare a thread for a debugging operation. |
21 | * Prepare a thread for a debugging operation. |
51 | * |
22 | * |
52 | * Simply put, return thread t with t->debug_lock held, |
23 | * Simply put, return thread t with t->debug_lock held, |
53 | * but only if it verifies all conditions. |
24 | * but only if it verifies all conditions. |
54 | * |
25 | * |
55 | * Specifically, verifies that thread t exists, is a userspace thread, |
26 | * Specifically, verifies that thread t exists, is a userspace thread, |
56 | * belongs to the callee of 'phone'. It also locks t->debug_lock, |
27 | * and belongs to the current task (TASK). It also locks t->debug_lock, |
57 | * making sure that t->debug_active is true - that the thread is |
28 | * making sure that t->debug_active is true - that the thread is |
58 | * in a valid debugging session. |
29 | * in a valid debugging session. |
59 | * |
30 | * |
60 | * Returns EOK if all went well, or an error code otherwise. |
31 | * Returns EOK if all went well, or an error code otherwise. |
61 | * Interrupts must be already disabled when calling this function. |
32 | * Interrupts must be already disabled when calling this function. |
62 | * |
33 | * |
63 | * Note: This function sports complicated locking. |
34 | * Note: This function sports complicated locking. |
64 | */ |
35 | */ |
65 | static int _thread_op_begin(phone_t *phone, thread_t *t) |
36 | static int _thread_op_begin(thread_t *t) |
66 | { |
37 | { |
67 | int rc; |
38 | int rc; |
68 | task_id_t taskid; |
39 | task_id_t taskid; |
69 | int task_match; |
- | |
70 | DEADLOCK_PROBE_INIT(p_tasklock); |
- | |
71 | 40 | ||
72 | taskid = get_callee_task_id(phone); |
41 | taskid = TASK->taskid; |
73 | 42 | ||
74 | /* Need to lock down the thread and than it's owner task */ |
43 | /* Must lock threads_lock to ensure continued existence of the thread */ |
75 | grab_locks: |
- | |
76 | spinlock_lock(&threads_lock); |
44 | spinlock_lock(&threads_lock); |
77 | 45 | ||
78 | if (!thread_exists(t)) { |
46 | if (!thread_exists(t)) { |
79 | spinlock_unlock(&threads_lock); |
47 | spinlock_unlock(&threads_lock); |
80 | return ENOENT; |
48 | return ENOENT; |
81 | } |
49 | } |
82 | 50 | ||
83 | spinlock_lock(&t->debug_lock); |
51 | spinlock_lock(&t->debug_lock); |
84 | spinlock_lock(&t->lock); |
52 | spinlock_lock(&t->lock); |
85 | 53 | ||
86 | if (!spinlock_trylock(&t->task->lock)) { |
- | |
87 | spinlock_unlock(&t->lock); |
- | |
88 | spinlock_unlock(&t->debug_lock); |
- | |
89 | DEADLOCK_PROBE(p_tasklock, DEADLOCK_THRESHOLD); |
- | |
90 | goto grab_locks; /* avoid deadlock */ |
- | |
91 | } |
- | |
92 | - | ||
93 | /* Now verify that it's the callee */ |
54 | /* Now verify that it's the current task */ |
94 | task_match = (t->task->taskid == taskid); |
- | |
95 | - | ||
96 | spinlock_unlock(&t->task->lock); |
- | |
97 | - | ||
98 | if (!task_match) { |
55 | if (t->task != TASK) { |
99 | /* No such thread belonging to callee */ |
56 | /* No such thread belonging to callee */ |
100 | rc = ENOENT; |
57 | rc = ENOENT; |
101 | goto error_exit; |
58 | goto error_exit; |
102 | } |
59 | } |
103 | 60 | ||
Line 130... | Line 87... | ||
130 | 87 | ||
131 | /* No locks left here */ |
88 | /* No locks left here */ |
132 | return rc; /* Some errors occured */ |
89 | return rc; /* Some errors occured */ |
133 | } |
90 | } |
134 | 91 | ||
- | 92 | ||
135 | static void _thread_op_end(thread_t *t) |
93 | static void _thread_op_end(thread_t *t) |
136 | { |
94 | { |
137 | spinlock_unlock(&t->debug_lock); |
95 | spinlock_unlock(&t->debug_lock); |
138 | } |
96 | } |
139 | 97 | ||
140 | static int udebug_rp_go(call_t *call, phone_t *phone) |
- | |
141 | { |
- | |
142 | thread_t *t; |
- | |
143 | ipl_t ipl; |
- | |
144 | int rc; |
- | |
145 | - | ||
146 | klog_printf("debug_go()"); |
- | |
147 | - | ||
148 | t = (thread_t *)IPC_GET_ARG2(call->data); |
- | |
149 | - | ||
150 | ipl = interrupts_disable(); |
- | |
151 | - | ||
152 | /* On success, this will lock t->debug_lock */ |
- | |
153 | rc = _thread_op_begin(phone, t); |
- | |
154 | if (rc != EOK) { |
- | |
155 | interrupts_restore(ipl); |
- | |
156 | return rc; |
- | |
157 | } |
- | |
158 | - | ||
159 | t->debug_go_call = call; |
- | |
160 | t->debug_stop = false; |
- | |
161 | t->cur_event = 0; /* none */ |
- | |
162 | - | ||
163 | /* |
- | |
164 | * Neither t's lock nor threads_lock may be held during wakeup |
- | |
165 | */ |
- | |
166 | waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
- | |
167 | - | ||
168 | _thread_op_end(t); |
- | |
169 | interrupts_restore(ipl); |
- | |
170 | - | ||
171 | return 0; /* no backsend */ |
- | |
172 | } |
- | |
173 | - | ||
174 | static int udebug_rp_args_read(call_t *call, phone_t *phone) |
- | |
175 | { |
- | |
176 | thread_t *t; |
- | |
177 | void *uspace_buffer; |
- | |
178 | int rc; |
- | |
179 | ipl_t ipl; |
- | |
180 | unative_t buffer[6]; |
- | |
181 | - | ||
182 | klog_printf("debug_args_read()"); |
- | |
183 | - | ||
184 | t = (thread_t *)IPC_GET_ARG2(call->data); |
- | |
185 | - | ||
186 | ipl = interrupts_disable(); |
- | |
187 | - | ||
188 | /* On success, this will lock t->debug_lock */ |
- | |
189 | rc = _thread_op_begin(phone, t); |
- | |
190 | if (rc != EOK) { |
- | |
191 | interrupts_restore(ipl); |
- | |
192 | return rc; |
- | |
193 | } |
- | |
194 | - | ||
195 | /* Additionally we need to verify that we are inside a syscall */ |
- | |
196 | if (t->cur_event != UDEBUG_EVENT_SYSCALL) { |
- | |
197 | _thread_op_end(t); |
- | |
198 | interrupts_restore(ipl); |
- | |
199 | return EINVAL; |
- | |
200 | } |
- | |
201 | - | ||
202 | /* Copy to a local buffer before releasing the lock */ |
- | |
203 | memcpy(buffer, t->syscall_args, 6 * sizeof(unative_t)); |
- | |
204 | - | ||
205 | _thread_op_end(t); |
- | |
206 | interrupts_restore(ipl); |
- | |
207 | - | ||
208 | /* Now copy to userspace */ |
- | |
209 | - | ||
210 | uspace_buffer = (void *)IPC_GET_ARG3(call->data); |
- | |
211 | - | ||
212 | rc = copy_to_uspace(uspace_buffer, buffer, 6 * sizeof(unative_t)); |
- | |
213 | if (rc != 0) { |
- | |
214 | klog_printf("debug_args_read() - copy failed"); |
- | |
215 | return rc; |
- | |
216 | } |
- | |
217 | - | ||
218 | klog_printf("debug_args_read() done"); |
- | |
219 | return 1; /* actually need becksend with retval 0 */ |
- | |
220 | } |
- | |
221 | - | ||
222 | static int udebug_rp_regs_read(call_t *call, phone_t *phone) |
- | |
223 | { |
- | |
224 | thread_t *t; |
- | |
225 | void *uspace_buffer; |
- | |
226 | unative_t to_copy; |
- | |
227 | int rc; |
- | |
228 | istate_t *state; |
- | |
229 | istate_t state_copy; |
- | |
230 | ipl_t ipl; |
- | |
231 | - | ||
232 | klog_printf("debug_regs_read()"); |
- | |
233 | - | ||
234 | t = (thread_t *) IPC_GET_ARG2(call->data); |
- | |
235 | - | ||
236 | ipl = interrupts_disable(); |
- | |
237 | - | ||
238 | /* On success, this will lock t->debug_lock */ |
- | |
239 | rc = _thread_op_begin(phone, t); |
- | |
240 | if (rc != EOK) { |
- | |
241 | interrupts_restore(ipl); |
- | |
242 | return rc; |
- | |
243 | } |
- | |
244 | - | ||
245 | state = t->uspace_state; |
- | |
246 | if (state == NULL) { |
- | |
247 | _thread_op_end(t); |
- | |
248 | interrupts_restore(ipl); |
- | |
249 | klog_printf("debug_regs_read() - istate not available"); |
- | |
250 | return EBUSY; |
- | |
251 | } |
- | |
252 | - | ||
253 | /* Copy to a local buffer so that we can release the lock */ |
- | |
254 | memcpy(&state_copy, state, sizeof(state_copy)); |
- | |
255 | _thread_op_end(t); |
- | |
256 | interrupts_restore(ipl); |
- | |
257 | - | ||
258 | uspace_buffer = (void *)IPC_GET_ARG3(call->data); |
- | |
259 | to_copy = IPC_GET_ARG4(call->data); |
- | |
260 | if (to_copy > sizeof(istate_t)) to_copy = sizeof(istate_t); |
- | |
261 | - | ||
262 | rc = copy_to_uspace(uspace_buffer, &state_copy, to_copy); |
- | |
263 | if (rc != 0) { |
- | |
264 | klog_printf("debug_regs_read() - copy failed"); |
- | |
265 | return rc; |
- | |
266 | } |
- | |
267 | - | ||
268 | IPC_SET_ARG1(call->data, to_copy); |
- | |
269 | IPC_SET_ARG2(call->data, sizeof(istate_t)); |
- | |
270 | - | ||
271 | klog_printf("debug_regs_read() done"); |
- | |
272 | return 1; /* actually need becksend with retval 0 */ |
- | |
273 | } |
- | |
274 | - | ||
275 | - | ||
276 | - | ||
277 | static int udebug_rp_regs_write(call_t *call, phone_t *phone) |
98 | static int udebug_rp_regs_write(call_t *call, phone_t *phone) |
278 | { |
99 | { |
279 | thread_t *t; |
- | |
280 | void *uspace_data; |
100 | void *uspace_data; |
281 | unative_t to_copy; |
101 | unative_t to_copy; |
282 | int rc; |
102 | int rc; |
283 | istate_t *state; |
103 | void *buffer; |
284 | istate_t data_copy; |
- | |
285 | ipl_t ipl; |
- | |
286 | 104 | ||
287 | klog_printf("debug_regs_write()"); |
105 | klog_printf("debug_regs_write()"); |
288 | 106 | ||
289 | /* First copy to a local buffer */ |
- | |
290 | - | ||
291 | uspace_data = (void *)IPC_GET_ARG3(call->data); |
107 | uspace_data = (void *)IPC_GET_ARG3(call->data); |
292 | to_copy = IPC_GET_ARG4(call->data); |
108 | to_copy = IPC_GET_ARG4(call->data); |
293 | if (to_copy > sizeof(istate_t)) to_copy = sizeof(istate_t); |
109 | if (to_copy > sizeof(istate_t)) to_copy = sizeof(istate_t); |
294 | 110 | ||
- | 111 | buffer = malloc(to_copy, 0); // ??? |
|
- | 112 | ||
295 | rc = copy_from_uspace(&data_copy, uspace_data, to_copy); |
113 | rc = copy_from_uspace(buffer, uspace_data, to_copy); |
296 | if (rc != 0) { |
114 | if (rc != 0) { |
297 | klog_printf("debug_regs_write() - copy failed"); |
115 | klog_printf("debug_regs_write() - copy failed"); |
298 | return rc; |
116 | return rc; |
299 | } |
117 | } |
300 | 118 | ||
301 | /* Now try to change the thread's uspace_state */ |
- | |
302 | - | ||
303 | ipl = interrupts_disable(); |
- | |
304 | t = (thread_t *) IPC_GET_ARG2(call->data); |
- | |
305 | - | ||
306 | /* On success, this will lock t->debug_lock */ |
- | |
307 | rc = _thread_op_begin(phone, t); |
- | |
308 | if (rc != EOK) { |
- | |
309 | interrupts_restore(ipl); |
- | |
310 | return rc; |
- | |
311 | } |
- | |
312 | - | ||
313 | state = t->uspace_state; |
- | |
314 | if (state == NULL) { |
- | |
315 | _thread_op_end(t); |
- | |
316 | interrupts_restore(ipl); |
- | |
317 | klog_printf("debug_regs_write() - istate not available"); |
- | |
318 | return EBUSY; |
- | |
319 | } |
- | |
320 | - | ||
321 | memcpy(t->uspace_state, &data_copy, sizeof(t->uspace_state)); |
- | |
322 | - | ||
323 | _thread_op_end(t); |
- | |
324 | interrupts_restore(ipl); |
- | |
325 | - | ||
326 | /* Set answer values */ |
119 | call->buffer = buffer; |
327 | - | ||
328 | IPC_SET_ARG1(call->data, to_copy); |
- | |
329 | IPC_SET_ARG2(call->data, sizeof(istate_t)); |
- | |
330 | 120 | ||
331 | klog_printf("debug_regs_write() done"); |
121 | klog_printf(" - done"); |
332 | return 1; /* actually need becksend with retval 0 */ |
122 | return 0; /* No backsend */ |
333 | } |
123 | } |
334 | 124 | ||
335 | static int udebug_rp_mem_write(call_t *call, phone_t *phone) |
125 | static int udebug_rp_mem_write(call_t *call, phone_t *phone) |
336 | { |
126 | { |
337 | void *uspace_data; |
127 | void *uspace_data; |
Line 362... | Line 152... | ||
362 | int udebug_request_preprocess(call_t *call, phone_t *phone) |
152 | int udebug_request_preprocess(call_t *call, phone_t *phone) |
363 | { |
153 | { |
364 | int rc; |
154 | int rc; |
365 | 155 | ||
366 | switch (IPC_GET_ARG1(call->data)) { |
156 | switch (IPC_GET_ARG1(call->data)) { |
367 | case UDEBUG_M_GO: |
- | |
368 | rc = udebug_rp_go(call, phone); |
- | |
369 | return rc; |
- | |
370 | case UDEBUG_M_ARGS_READ: |
- | |
371 | rc = udebug_rp_args_read(call, phone); |
- | |
372 | return rc; |
- | |
373 | case UDEBUG_M_REGS_READ: |
- | |
374 | rc = udebug_rp_regs_read(call, phone); |
- | |
375 | return rc; |
- | |
376 | case UDEBUG_M_REGS_WRITE: |
157 | case UDEBUG_M_REGS_WRITE: |
377 | rc = udebug_rp_regs_write(call, phone); |
158 | rc = udebug_rp_regs_write(call, phone); |
378 | return rc; |
159 | return rc; |
379 | case UDEBUG_M_MEM_WRITE: |
160 | case UDEBUG_M_MEM_WRITE: |
380 | rc = udebug_rp_mem_write(call, phone); |
161 | rc = udebug_rp_mem_write(call, phone); |
Line 467... | Line 248... | ||
467 | 248 | ||
468 | IPC_SET_RETVAL(call->data, 0); |
249 | IPC_SET_RETVAL(call->data, 0); |
469 | ipc_answer(&TASK->kernel_box, call); |
250 | ipc_answer(&TASK->kernel_box, call); |
470 | } |
251 | } |
471 | 252 | ||
- | 253 | static void udebug_receive_go(call_t *call) |
|
- | 254 | { |
|
- | 255 | thread_t *t; |
|
- | 256 | ipl_t ipl; |
|
- | 257 | int rc; |
|
- | 258 | ||
- | 259 | klog_printf("debug_go()"); |
|
- | 260 | ||
- | 261 | t = (thread_t *)IPC_GET_ARG2(call->data); |
|
- | 262 | ||
- | 263 | ipl = interrupts_disable(); |
|
- | 264 | ||
- | 265 | /* On success, this will lock t->debug_lock */ |
|
- | 266 | rc = _thread_op_begin(t); |
|
- | 267 | if (rc != EOK) { |
|
- | 268 | interrupts_restore(ipl); |
|
- | 269 | ||
- | 270 | IPC_SET_RETVAL(call->data, rc); |
|
- | 271 | ipc_answer(&TASK->kernel_box, call); |
|
- | 272 | return; |
|
- | 273 | } |
|
- | 274 | ||
- | 275 | t->debug_go_call = call; |
|
- | 276 | t->debug_stop = false; |
|
- | 277 | t->cur_event = 0; /* none */ |
|
- | 278 | ||
- | 279 | /* |
|
- | 280 | * Neither t's lock nor threads_lock may be held during wakeup |
|
- | 281 | */ |
|
- | 282 | waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
|
- | 283 | ||
- | 284 | _thread_op_end(t); |
|
- | 285 | interrupts_restore(ipl); |
|
- | 286 | ||
- | 287 | /* No reply */ |
|
- | 288 | } |
|
- | 289 | ||
- | 290 | ||
472 | static void udebug_receive_thread_read(call_t *call) |
291 | static void udebug_receive_thread_read(call_t *call) |
473 | { |
292 | { |
474 | thread_t *t; |
293 | thread_t *t; |
475 | link_t *cur; |
294 | link_t *cur; |
476 | unative_t uspace_addr; |
295 | unative_t uspace_addr; |
Line 553... | Line 372... | ||
553 | call->buffer = (void *)buffer; |
372 | call->buffer = (void *)buffer; |
554 | 373 | ||
555 | ipc_answer(&TASK->kernel_box, call); |
374 | ipc_answer(&TASK->kernel_box, call); |
556 | } |
375 | } |
557 | 376 | ||
- | 377 | static void udebug_receive_args_read(call_t *call) |
|
- | 378 | { |
|
- | 379 | thread_t *t; |
|
- | 380 | unative_t uspace_addr; |
|
- | 381 | int rc; |
|
- | 382 | ipl_t ipl; |
|
- | 383 | unative_t *buffer; |
|
- | 384 | ||
- | 385 | klog_printf("debug_args_read()"); |
|
- | 386 | ||
- | 387 | t = (thread_t *)IPC_GET_ARG2(call->data); |
|
- | 388 | ||
- | 389 | ipl = interrupts_disable(); |
|
- | 390 | ||
- | 391 | /* On success, this will lock t->debug_lock */ |
|
- | 392 | rc = _thread_op_begin(t); |
|
- | 393 | if (rc != EOK) { |
|
- | 394 | interrupts_restore(ipl); |
|
- | 395 | IPC_SET_RETVAL(call->data, rc); |
|
- | 396 | ipc_answer(&TASK->kernel_box, call); |
|
- | 397 | return; |
|
- | 398 | } |
|
- | 399 | ||
- | 400 | /* Additionally we need to verify that we are inside a syscall */ |
|
- | 401 | if (t->cur_event != UDEBUG_EVENT_SYSCALL) { |
|
- | 402 | _thread_op_end(t); |
|
- | 403 | interrupts_restore(ipl); |
|
- | 404 | ||
- | 405 | IPC_SET_RETVAL(call->data, EINVAL); |
|
- | 406 | ipc_answer(&TASK->kernel_box, call); |
|
- | 407 | return; |
|
- | 408 | } |
|
- | 409 | ||
- | 410 | /* Copy to a local buffer before releasing the lock */ |
|
- | 411 | buffer = malloc(6 * sizeof(unative_t), 0); // ??? |
|
- | 412 | memcpy(buffer, t->syscall_args, 6 * sizeof(unative_t)); |
|
- | 413 | ||
- | 414 | _thread_op_end(t); |
|
- | 415 | interrupts_restore(ipl); |
|
- | 416 | ||
- | 417 | /* |
|
- | 418 | * Make use of call->buffer to transfer data to caller's userspace |
|
- | 419 | */ |
|
- | 420 | ||
- | 421 | uspace_addr = IPC_GET_ARG3(call->data); |
|
- | 422 | ||
- | 423 | IPC_SET_RETVAL(call->data, 0); |
|
- | 424 | /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that |
|
- | 425 | same code in process_answer() can be used |
|
- | 426 | (no way to distinguish method in answer) */ |
|
- | 427 | IPC_SET_ARG1(call->data, uspace_addr); |
|
- | 428 | IPC_SET_ARG2(call->data, 6 * sizeof(unative_t)); |
|
- | 429 | call->buffer = (void *)buffer; |
|
- | 430 | ||
- | 431 | ipc_answer(&TASK->kernel_box, call); |
|
- | 432 | } |
|
- | 433 | ||
- | 434 | static void udebug_receive_regs_read(call_t *call) |
|
- | 435 | { |
|
- | 436 | thread_t *t; |
|
- | 437 | unative_t uspace_addr; |
|
- | 438 | unative_t to_copy; |
|
- | 439 | unative_t buf_size; |
|
- | 440 | unative_t total_bytes; |
|
- | 441 | istate_t *state; |
|
- | 442 | void *buffer; |
|
- | 443 | int rc; |
|
- | 444 | ipl_t ipl; |
|
- | 445 | ||
- | 446 | klog_printf("debug_regs_read()"); |
|
- | 447 | ||
- | 448 | t = (thread_t *) IPC_GET_ARG2(call->data); |
|
- | 449 | ||
- | 450 | ipl = interrupts_disable(); |
|
- | 451 | ||
- | 452 | /* On success, this will lock t->debug_lock */ |
|
- | 453 | rc = _thread_op_begin(t); |
|
- | 454 | if (rc != EOK) { |
|
- | 455 | interrupts_restore(ipl); |
|
- | 456 | ||
- | 457 | IPC_SET_RETVAL(call->data, rc); |
|
- | 458 | ipc_answer(&TASK->kernel_box, call); |
|
- | 459 | return; |
|
- | 460 | } |
|
- | 461 | ||
- | 462 | state = t->uspace_state; |
|
- | 463 | if (state == NULL) { |
|
- | 464 | _thread_op_end(t); |
|
- | 465 | interrupts_restore(ipl); |
|
- | 466 | klog_printf("debug_regs_read() - istate not available"); |
|
- | 467 | ||
- | 468 | IPC_SET_RETVAL(call->data, EBUSY); |
|
- | 469 | ipc_answer(&TASK->kernel_box, call); |
|
- | 470 | return; |
|
- | 471 | } |
|
- | 472 | ||
- | 473 | /* Copy to an allocated buffer */ |
|
- | 474 | buffer = malloc(sizeof(istate_t), 0); // ??? |
|
- | 475 | memcpy(buffer, state, sizeof(istate_t)); |
|
- | 476 | ||
- | 477 | _thread_op_end(t); |
|
- | 478 | interrupts_restore(ipl); |
|
- | 479 | ||
- | 480 | /* |
|
- | 481 | * Make use of call->buffer to transfer data to caller's userspace |
|
- | 482 | */ |
|
- | 483 | ||
- | 484 | uspace_addr = IPC_GET_ARG3(call->data); |
|
- | 485 | buf_size = IPC_GET_ARG4(call->data); |
|
- | 486 | ||
- | 487 | total_bytes = sizeof(istate_t); |
|
- | 488 | ||
- | 489 | if (buf_size > total_bytes) |
|
- | 490 | to_copy = total_bytes; |
|
- | 491 | else |
|
- | 492 | to_copy = buf_size; |
|
- | 493 | ||
- | 494 | IPC_SET_RETVAL(call->data, 0); |
|
- | 495 | /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that |
|
- | 496 | same code in process_answer() can be used |
|
- | 497 | (no way to distinguish method in answer) */ |
|
- | 498 | IPC_SET_ARG1(call->data, uspace_addr); |
|
- | 499 | IPC_SET_ARG2(call->data, to_copy); |
|
- | 500 | ||
- | 501 | IPC_SET_ARG3(call->data, total_bytes); |
|
- | 502 | call->buffer = (void *)buffer; |
|
- | 503 | ||
- | 504 | ipc_answer(&TASK->kernel_box, call); |
|
- | 505 | } |
|
- | 506 | ||
- | 507 | static void udebug_receive_regs_write(call_t *call) |
|
- | 508 | { |
|
- | 509 | thread_t *t; |
|
- | 510 | void *uspace_data; |
|
- | 511 | unative_t to_copy; |
|
- | 512 | int rc; |
|
- | 513 | istate_t *state; |
|
- | 514 | ipl_t ipl; |
|
- | 515 | ||
- | 516 | klog_printf("debug_regs_write()"); |
|
- | 517 | ||
- | 518 | uspace_data = (void *)IPC_GET_ARG3(call->data); |
|
- | 519 | to_copy = IPC_GET_ARG4(call->data); |
|
- | 520 | ||
- | 521 | /* Try to change the thread's uspace_state */ |
|
- | 522 | ||
- | 523 | ipl = interrupts_disable(); |
|
- | 524 | t = (thread_t *) IPC_GET_ARG2(call->data); |
|
- | 525 | ||
- | 526 | /* On success, this will lock t->debug_lock */ |
|
- | 527 | rc = _thread_op_begin(t); |
|
- | 528 | if (rc != EOK) { |
|
- | 529 | interrupts_restore(ipl); |
|
- | 530 | ||
- | 531 | IPC_SET_RETVAL(call->data, rc); |
|
- | 532 | ipc_answer(&TASK->kernel_box, call); |
|
- | 533 | return; |
|
- | 534 | } |
|
- | 535 | ||
- | 536 | state = t->uspace_state; |
|
- | 537 | if (state == NULL) { |
|
- | 538 | _thread_op_end(t); |
|
- | 539 | interrupts_restore(ipl); |
|
- | 540 | klog_printf("debug_regs_write() - istate not available"); |
|
- | 541 | ||
- | 542 | IPC_SET_RETVAL(call->data, EBUSY); |
|
- | 543 | ipc_answer(&TASK->kernel_box, call); |
|
- | 544 | return; |
|
- | 545 | } |
|
- | 546 | ||
- | 547 | memcpy(t->uspace_state, call->buffer, sizeof(t->uspace_state)); |
|
- | 548 | ||
- | 549 | _thread_op_end(t); |
|
- | 550 | interrupts_restore(ipl); |
|
- | 551 | ||
- | 552 | /* Set answer values */ |
|
- | 553 | ||
- | 554 | IPC_SET_ARG1(call->data, to_copy); |
|
- | 555 | IPC_SET_ARG2(call->data, sizeof(istate_t)); |
|
- | 556 | ||
- | 557 | IPC_SET_RETVAL(call->data, 0); |
|
- | 558 | ipc_answer(&TASK->kernel_box, call); |
|
- | 559 | ||
- | 560 | klog_printf("debug_regs_write() done"); |
|
- | 561 | } |
|
- | 562 | ||
558 | 563 | ||
559 | static void udebug_receive_mem_read(call_t *call) |
564 | static void udebug_receive_mem_read(call_t *call) |
560 | { |
565 | { |
561 | unative_t uspace_dst; |
566 | unative_t uspace_dst; |
562 | void *uspace_ptr; |
567 | void *uspace_ptr; |
Line 575... | Line 580... | ||
575 | /* NOTE: this is not strictly from a syscall... but that shouldn't |
580 | /* NOTE: this is not strictly from a syscall... but that shouldn't |
576 | * be a problem */ |
581 | * be a problem */ |
577 | rc = copy_from_uspace(buffer, uspace_ptr, size); |
582 | rc = copy_from_uspace(buffer, uspace_ptr, size); |
578 | if (rc) { |
583 | if (rc) { |
579 | IPC_SET_RETVAL(call->data, rc); |
584 | IPC_SET_RETVAL(call->data, rc); |
- | 585 | ipc_answer(&TASK->kernel_box, call); |
|
580 | return; |
586 | return; |
581 | } |
587 | } |
582 | 588 | ||
583 | klog_printf("first word: %u", *((unative_t *)buffer)); |
589 | klog_printf("first word: %u", *((unative_t *)buffer)); |
584 | 590 | ||
Line 654... | Line 660... | ||
654 | udebug_receive_begin(call); |
660 | udebug_receive_begin(call); |
655 | break; |
661 | break; |
656 | case UDEBUG_M_END: |
662 | case UDEBUG_M_END: |
657 | udebug_receive_end(call); |
663 | udebug_receive_end(call); |
658 | break; |
664 | break; |
- | 665 | case UDEBUG_M_GO: |
|
- | 666 | udebug_receive_go(call); |
|
- | 667 | break; |
|
659 | case UDEBUG_M_THREAD_READ: |
668 | case UDEBUG_M_THREAD_READ: |
660 | udebug_receive_thread_read(call); |
669 | udebug_receive_thread_read(call); |
661 | break; |
670 | break; |
- | 671 | case UDEBUG_M_ARGS_READ: |
|
- | 672 | udebug_receive_args_read(call); |
|
- | 673 | break; |
|
- | 674 | case UDEBUG_M_REGS_READ: |
|
- | 675 | udebug_receive_regs_read(call); |
|
- | 676 | break; |
|
- | 677 | case UDEBUG_M_REGS_WRITE: |
|
- | 678 | udebug_receive_regs_write(call); |
|
- | 679 | break; |
|
662 | case UDEBUG_M_MEM_READ: |
680 | case UDEBUG_M_MEM_READ: |
663 | udebug_receive_mem_read(call); |
681 | udebug_receive_mem_read(call); |
664 | break; |
682 | break; |
665 | case UDEBUG_M_MEM_WRITE: |
683 | case UDEBUG_M_MEM_WRITE: |
666 | udebug_receive_mem_write(call); |
684 | udebug_receive_mem_write(call); |