Rev 2834 | Rev 2838 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2834 | Rev 2835 | ||
---|---|---|---|
1 | /** @addtogroup generic |
1 | /** @addtogroup generic |
2 | * @{ |
2 | * @{ |
3 | */ |
3 | */ |
4 | 4 | ||
5 | /** |
5 | /** |
6 | * @file |
6 | * @file |
7 | * @brief Tdebug. |
7 | * @brief Tdebug. |
8 | */ |
8 | */ |
9 | 9 | ||
10 | #include <console/klog.h> |
10 | #include <console/klog.h> |
11 | #include <proc/task.h> |
11 | #include <proc/task.h> |
12 | #include <proc/thread.h> |
12 | #include <proc/thread.h> |
13 | #include <arch.h> |
13 | #include <arch.h> |
14 | #include <errno.h> |
14 | #include <errno.h> |
15 | #include <ipc/ipc.h> |
15 | #include <ipc/ipc.h> |
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 and lock a phone's callee task. |
21 | * Get and lock a phone's callee task. |
22 | * |
22 | * |
23 | * This will return a pointer to the task to which the phone |
23 | * This will return a pointer to the task to which the phone |
24 | * is connected. It will lock the task, making sure it exists. |
24 | * is connected. It will lock the task, making sure it exists. |
25 | * (TODO: make sure the udebug-cleanup of the task hasn't |
25 | * (TODO: make sure the udebug-cleanup of the task hasn't |
26 | * started yet) |
26 | * started yet) |
27 | */ |
27 | */ |
28 | static task_t *get_lock_callee_task(phone_t *phone) |
28 | static task_t *get_lock_callee_task(phone_t *phone) |
29 | { |
29 | { |
30 | answerbox_t *box; |
30 | answerbox_t *box; |
31 | task_t *ta; |
31 | task_t *ta; |
32 | task_id_t taskid; |
32 | task_id_t taskid; |
33 | ipl_t ipl; |
33 | ipl_t ipl; |
34 | 34 | ||
35 | ipl = interrupts_disable(); |
35 | ipl = interrupts_disable(); |
36 | spinlock_lock(&phone->lock); |
36 | spinlock_lock(&phone->lock); |
37 | if (phone->state != IPC_PHONE_CONNECTED) { |
37 | if (phone->state != IPC_PHONE_CONNECTED) { |
38 | spinlock_unlock(&phone->lock); |
38 | spinlock_unlock(&phone->lock); |
39 | interrupts_restore(ipl); |
39 | interrupts_restore(ipl); |
40 | return NULL; |
40 | return NULL; |
41 | } |
41 | } |
42 | 42 | ||
43 | box = phone->callee; |
43 | box = phone->callee; |
44 | 44 | ||
45 | spinlock_lock(&box->lock); |
45 | spinlock_lock(&box->lock); |
46 | ta = box->task; |
46 | ta = box->task; |
47 | taskid = ta->taskid; |
47 | taskid = ta->taskid; |
48 | spinlock_unlock(&box->lock); |
48 | spinlock_unlock(&box->lock); |
49 | spinlock_unlock(&phone->lock); |
49 | spinlock_unlock(&phone->lock); |
50 | 50 | ||
51 | /* Locking decoupled using taskid */ |
51 | /* Locking decoupled using taskid */ |
52 | 52 | ||
53 | spinlock_lock(&tasks_lock); |
53 | spinlock_lock(&tasks_lock); |
54 | ta = task_find_by_id(taskid); |
54 | ta = task_find_by_id(taskid); |
55 | if (ta == NULL) { |
55 | if (ta == NULL) { |
56 | spinlock_unlock(&tasks_lock); |
56 | spinlock_unlock(&tasks_lock); |
57 | interrupts_restore(ipl); |
57 | interrupts_restore(ipl); |
58 | return NULL; |
58 | return NULL; |
59 | } |
59 | } |
60 | 60 | ||
61 | spinlock_lock(&ta->lock); |
61 | spinlock_lock(&ta->lock); |
62 | spinlock_unlock(&tasks_lock); |
62 | spinlock_unlock(&tasks_lock); |
63 | interrupts_restore(ipl); |
63 | interrupts_restore(ipl); |
64 | 64 | ||
65 | return ta; |
65 | return ta; |
66 | } |
66 | } |
67 | 67 | ||
68 | static int udebug_rp_begin(call_t *call, phone_t *phone) |
68 | static int udebug_rp_begin(call_t *call, phone_t *phone) |
69 | { |
69 | { |
70 | task_t *ta; |
70 | task_t *ta; |
71 | ipl_t ipl; |
71 | ipl_t ipl; |
72 | int rc; |
72 | int rc; |
73 | 73 | ||
74 | thread_t *t; |
74 | thread_t *t; |
75 | link_t *cur; |
75 | link_t *cur; |
76 | 76 | ||
77 | klog_printf("debug_begin()"); |
77 | klog_printf("debug_begin()"); |
78 | 78 | ||
79 | ipl = interrupts_disable(); |
79 | ipl = interrupts_disable(); |
80 | ta = get_lock_callee_task(phone); |
80 | ta = get_lock_callee_task(phone); |
81 | klog_printf("debugging task %llu", ta->taskid); |
81 | klog_printf("debugging task %llu", ta->taskid); |
82 | 82 | ||
83 | if (ta->dt_state != UDEBUG_TS_INACTIVE) { |
83 | if (ta->dt_state != UDEBUG_TS_INACTIVE) { |
84 | spinlock_unlock(&ta->lock); |
84 | spinlock_unlock(&ta->lock); |
85 | interrupts_restore(ipl); |
85 | interrupts_restore(ipl); |
86 | klog_printf("debug_begin(): busy error"); |
86 | klog_printf("debug_begin(): busy error"); |
87 | return EBUSY; |
87 | return EBUSY; |
88 | } |
88 | } |
89 | 89 | ||
90 | ta->dt_state = UDEBUG_TS_BEGINNING; |
90 | ta->dt_state = UDEBUG_TS_BEGINNING; |
91 | ta->debug_begin_call = call; |
91 | ta->debug_begin_call = call; |
92 | 92 | ||
93 | if (ta->not_stoppable_count == 0) { |
93 | if (ta->not_stoppable_count == 0) { |
94 | ta->dt_state = UDEBUG_TS_ACTIVE; |
94 | ta->dt_state = UDEBUG_TS_ACTIVE; |
95 | ta->debug_begin_call = NULL; |
95 | ta->debug_begin_call = NULL; |
96 | rc = 1; /* actually we need backsend with 0 retval */ |
96 | rc = 1; /* actually we need backsend with 0 retval */ |
97 | } else { |
97 | } else { |
98 | rc = 0; /* no backsend */ |
98 | rc = 0; /* no backsend */ |
99 | } |
99 | } |
100 | 100 | ||
101 | /* Set debug_active on all of the task's userspace threads */ |
101 | /* Set debug_active on all of the task's userspace threads */ |
102 | 102 | ||
103 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
103 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
104 | t = list_get_instance(cur, thread_t, th_link); |
104 | t = list_get_instance(cur, thread_t, th_link); |
105 | 105 | ||
106 | spinlock_lock(&t->lock); |
106 | spinlock_lock(&t->lock); |
107 | if ((t->flags & THREAD_FLAG_USPACE) != 0) |
107 | if ((t->flags & THREAD_FLAG_USPACE) != 0) |
108 | t->debug_active = true; |
108 | t->debug_active = true; |
109 | spinlock_unlock(&t->lock); |
109 | spinlock_unlock(&t->lock); |
110 | } |
110 | } |
111 | 111 | ||
112 | spinlock_unlock(&ta->lock); |
112 | spinlock_unlock(&ta->lock); |
113 | interrupts_restore(ipl); |
113 | interrupts_restore(ipl); |
114 | 114 | ||
115 | klog_printf("debug_begin() done (%s)", |
115 | klog_printf("debug_begin() done (%s)", |
116 | rc ? "backsend" : "stoppability wait"); |
116 | rc ? "backsend" : "stoppability wait"); |
117 | 117 | ||
118 | return rc; |
118 | return rc; |
119 | } |
119 | } |
120 | 120 | ||
121 | static int udebug_rp_end(call_t *call, phone_t *phone) |
121 | static int udebug_rp_end(call_t *call, phone_t *phone) |
122 | { |
122 | { |
123 | task_t *ta; |
123 | task_t *ta; |
124 | ipl_t ipl; |
124 | ipl_t ipl; |
125 | 125 | ||
126 | thread_t *t; |
126 | thread_t *t; |
127 | link_t *cur; |
127 | link_t *cur; |
128 | 128 | ||
129 | klog_printf("udebug_rp_end()"); |
129 | klog_printf("udebug_rp_end()"); |
130 | 130 | ||
131 | ipl = interrupts_disable(); |
131 | ipl = interrupts_disable(); |
132 | ta = get_lock_callee_task(phone); |
132 | ta = get_lock_callee_task(phone); |
133 | klog_printf("task %llu", ta->taskid); |
133 | klog_printf("task %llu", ta->taskid); |
134 | 134 | ||
135 | //TODO: UDEBUG_TS_BEGINNING |
135 | if (ta->dt_state == UDEBUG_TS_BEGINNING && |
136 | if (ta->dt_state != UDEBUG_TS_ACTIVE) { |
136 | ta->dt_state != UDEBUG_TS_ACTIVE) { |
137 | spinlock_unlock(&ta->lock); |
137 | spinlock_unlock(&ta->lock); |
138 | interrupts_restore(ipl); |
138 | interrupts_restore(ipl); |
139 | klog_printf("udebug_rp_begin(): task not in TS_BEGINNING"); |
139 | klog_printf("udebug_rp_begin(): task not being debugged"); |
140 | return EINVAL; |
140 | return EINVAL; |
141 | } |
141 | } |
142 | 142 | ||
143 | /* Clear debug_active from all of the task's userspace threads */ |
143 | /* Finish debugging of all userspace threads */ |
144 | - | ||
145 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
144 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
146 | t = list_get_instance(cur, thread_t, th_link); |
145 | t = list_get_instance(cur, thread_t, th_link); |
147 | 146 | ||
148 | spinlock_lock(&t->lock); |
147 | spinlock_lock(&t->lock); |
149 | if ((t->flags & THREAD_FLAG_USPACE) != 0) |
- | |
150 | t->debug_active = true; |
- | |
151 | spinlock_unlock(&t->lock); |
- | |
152 | } |
- | |
153 | 148 | ||
154 | /* Now respond to unanswered GO calls and reset thread states */ |
149 | /* Only process userspace threads */ |
155 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
150 | if ((t->flags & THREAD_FLAG_USPACE) != 0) { |
156 | t = list_get_instance(cur, thread_t, th_link); |
151 | /* Prevent any further debug activity in thread */ |
157 | - | ||
158 | spinlock_lock(&t->lock); |
152 | t->debug_active = false; |
159 | 153 | ||
160 | /* Still has go? */ |
154 | /* Still has go? */ |
161 | if ((t->flags & THREAD_FLAG_USPACE) != 0 && |
- | |
162 | t->debug_stop == false) { |
155 | if (t->debug_stop == false) { |
163 | /* |
156 | /* |
164 | * Yes, so clear go. As debug_active == false, |
157 | * Yes, so clear go. As debug_active == false, |
165 | * this doesn't affect anything. |
158 | * this doesn't affect anything. |
166 | */ |
159 | */ |
167 | t->debug_stop = true; |
160 | t->debug_stop = true; |
168 | 161 | ||
169 | /* Answer GO call */ |
162 | /* Answer GO call */ |
170 | ipc_answer(&ta->answerbox, t->debug_go_call); |
163 | ipc_answer(&ta->answerbox, t->debug_go_call); |
171 | } else { |
164 | } else { |
172 | /* |
165 | /* |
173 | * Debug_stop is already at initial value. |
166 | * Debug_stop is already at initial value. |
174 | * Yet this means the thread needs waking up. |
167 | * Yet this means the thread needs waking up. |
175 | */ |
168 | */ |
176 | waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
169 | waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
- | 170 | } |
|
177 | } |
171 | } |
- | 172 | ||
178 | spinlock_unlock(&t->lock); |
173 | spinlock_unlock(&t->lock); |
179 | } |
174 | } |
180 | 175 | ||
181 | ta->dt_state = UDEBUG_TS_INACTIVE; |
176 | ta->dt_state = UDEBUG_TS_INACTIVE; |
182 | 177 | ||
183 | spinlock_unlock(&ta->lock); |
178 | spinlock_unlock(&ta->lock); |
184 | interrupts_restore(ipl); |
179 | interrupts_restore(ipl); |
185 | 180 | ||
186 | klog_printf("udebug_rp_end() done\n"); |
181 | klog_printf("udebug_rp_end() done\n"); |
187 | 182 | ||
188 | return 1; |
183 | return 1; |
189 | } |
184 | } |
190 | 185 | ||
191 | 186 | ||
192 | static int udebug_rp_go(call_t *call, phone_t *phone) |
187 | static int udebug_rp_go(call_t *call, phone_t *phone) |
193 | { |
188 | { |
194 | thread_t *t; |
189 | thread_t *t; |
195 | task_t *ta; |
190 | task_t *ta; |
196 | ipl_t ipl; |
191 | ipl_t ipl; |
197 | 192 | ||
198 | klog_printf("debug_go()"); |
193 | klog_printf("debug_go()"); |
199 | ta = get_lock_callee_task(phone); |
194 | ta = get_lock_callee_task(phone); |
200 | spinlock_unlock(&ta->lock); |
195 | spinlock_unlock(&ta->lock); |
201 | // TODO: don't lock ta |
196 | // TODO: don't lock ta |
202 | 197 | ||
203 | t = (thread_t *) IPC_GET_ARG2(call->data); |
198 | t = (thread_t *) IPC_GET_ARG2(call->data); |
204 | 199 | ||
205 | ipl = interrupts_disable(); |
200 | ipl = interrupts_disable(); |
206 | spinlock_lock(&threads_lock); |
201 | spinlock_lock(&threads_lock); |
207 | 202 | ||
208 | /* Verify that 't' exists and belongs to task 'ta' */ |
203 | /* Verify that 't' exists and belongs to task 'ta' */ |
209 | if (!thread_exists(t) || (t->task != ta)) { |
204 | if (!thread_exists(t) || (t->task != ta)) { |
210 | spinlock_unlock(&threads_lock); |
205 | spinlock_unlock(&threads_lock); |
211 | interrupts_restore(ipl); |
206 | interrupts_restore(ipl); |
212 | return ENOENT; |
207 | return ENOENT; |
213 | } |
208 | } |
214 | 209 | ||
215 | if ((t->debug_active != true) || (t->debug_stop != true)) { |
210 | if ((t->debug_active != true) || (t->debug_stop != true)) { |
216 | /* Not in debugging session or already has GO */ |
211 | /* Not in debugging session or already has GO */ |
217 | spinlock_unlock(&threads_lock); |
212 | spinlock_unlock(&threads_lock); |
218 | interrupts_restore(ipl); |
213 | interrupts_restore(ipl); |
219 | return EBUSY; |
214 | return EBUSY; |
220 | } |
215 | } |
221 | 216 | ||
222 | t->debug_go_call = call; |
217 | t->debug_go_call = call; |
223 | t->debug_stop = false; |
218 | t->debug_stop = false; |
224 | waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
219 | waitq_wakeup(&t->go_wq, WAKEUP_FIRST); |
225 | 220 | ||
226 | spinlock_unlock(&threads_lock); |
221 | spinlock_unlock(&threads_lock); |
227 | interrupts_restore(ipl); |
222 | interrupts_restore(ipl); |
228 | 223 | ||
229 | return 0; /* no backsend */ |
224 | return 0; /* no backsend */ |
230 | } |
225 | } |
231 | 226 | ||
232 | static int udebug_rp_args_read(call_t *call, phone_t *phone) |
227 | static int udebug_rp_args_read(call_t *call, phone_t *phone) |
233 | { |
228 | { |
234 | thread_t *t; |
229 | thread_t *t; |
235 | task_t *ta; |
230 | task_t *ta; |
236 | void *uspace_buffer; |
231 | void *uspace_buffer; |
237 | int rc; |
232 | int rc; |
238 | ipl_t ipl; |
233 | ipl_t ipl; |
239 | unative_t buffer[6]; |
234 | unative_t buffer[6]; |
240 | 235 | ||
241 | klog_printf("debug_args_read()"); |
236 | klog_printf("debug_args_read()"); |
242 | 237 | ||
243 | ta = get_lock_callee_task(phone); |
238 | ta = get_lock_callee_task(phone); |
244 | klog_printf("task %llu", ta->taskid); |
239 | klog_printf("task %llu", ta->taskid); |
245 | spinlock_unlock(&ta->lock); |
240 | spinlock_unlock(&ta->lock); |
246 | 241 | ||
247 | t = (thread_t *) IPC_GET_ARG2(call->data); |
242 | t = (thread_t *) IPC_GET_ARG2(call->data); |
248 | 243 | ||
249 | ipl = interrupts_disable(); |
244 | ipl = interrupts_disable(); |
250 | spinlock_lock(&threads_lock); |
245 | spinlock_lock(&threads_lock); |
251 | 246 | ||
252 | /* Verify that 't' exists and belongs to task 'ta' */ |
247 | /* Verify that 't' exists and belongs to task 'ta' */ |
253 | if (!thread_exists(t) || (t->task != ta)) { |
248 | if (!thread_exists(t) || (t->task != ta)) { |
254 | spinlock_unlock(&threads_lock); |
249 | spinlock_unlock(&threads_lock); |
255 | interrupts_restore(ipl); |
250 | interrupts_restore(ipl); |
256 | return ENOENT; |
251 | return ENOENT; |
257 | } |
252 | } |
258 | 253 | ||
259 | //FIXME: additionally we need to verify that we are inside a syscall |
254 | //FIXME: additionally we need to verify that we are inside a syscall |
260 | if ((t->debug_active != true) || (t->debug_stop != true)) { |
255 | if ((t->debug_active != true) || (t->debug_stop != true)) { |
261 | /* Not in debugging session or has GO */ |
256 | /* Not in debugging session or has GO */ |
262 | spinlock_unlock(&threads_lock); |
257 | spinlock_unlock(&threads_lock); |
263 | interrupts_restore(ipl); |
258 | interrupts_restore(ipl); |
264 | return EBUSY; |
259 | return EBUSY; |
265 | } |
260 | } |
266 | 261 | ||
267 | /* Copy to a local buffer before releasing the lock */ |
262 | /* Copy to a local buffer before releasing the lock */ |
268 | memcpy(buffer, t->syscall_args, 6 * sizeof(unative_t)); |
263 | memcpy(buffer, t->syscall_args, 6 * sizeof(unative_t)); |
269 | 264 | ||
270 | spinlock_unlock(&threads_lock); |
265 | spinlock_unlock(&threads_lock); |
271 | interrupts_restore(ipl); |
266 | interrupts_restore(ipl); |
272 | 267 | ||
273 | /* Now copy to userspace */ |
268 | /* Now copy to userspace */ |
274 | 269 | ||
275 | uspace_buffer = (void *)IPC_GET_ARG3(call->data); |
270 | uspace_buffer = (void *)IPC_GET_ARG3(call->data); |
276 | 271 | ||
277 | rc = copy_to_uspace(uspace_buffer, buffer, 6 * sizeof(unative_t)); |
272 | rc = copy_to_uspace(uspace_buffer, buffer, 6 * sizeof(unative_t)); |
278 | if (rc != 0) { |
273 | if (rc != 0) { |
279 | spinlock_unlock(&ta->lock); |
274 | spinlock_unlock(&ta->lock); |
280 | klog_printf("debug_args_read() - copy failed"); |
275 | klog_printf("debug_args_read() - copy failed"); |
281 | return rc; |
276 | return rc; |
282 | } |
277 | } |
283 | 278 | ||
284 | klog_printf("debug_args_read() done"); |
279 | klog_printf("debug_args_read() done"); |
285 | return 1; /* actually need becksend with retval 0 */ |
280 | return 1; /* actually need becksend with retval 0 */ |
286 | } |
281 | } |
287 | 282 | ||
288 | static int udebug_rp_regs_read(call_t *call, phone_t *phone) |
283 | static int udebug_rp_regs_read(call_t *call, phone_t *phone) |
289 | { |
284 | { |
290 | thread_t *t; |
285 | thread_t *t; |
291 | task_t *ta; |
286 | task_t *ta; |
292 | void *uspace_buffer; |
287 | void *uspace_buffer; |
293 | unative_t to_copy; |
288 | unative_t to_copy; |
294 | int rc; |
289 | int rc; |
295 | istate_t *state; |
290 | istate_t *state; |
296 | istate_t state_copy; |
291 | istate_t state_copy; |
297 | ipl_t ipl; |
292 | ipl_t ipl; |
298 | 293 | ||
299 | klog_printf("debug_regs_read()"); |
294 | klog_printf("debug_regs_read()"); |
300 | 295 | ||
301 | ta = get_lock_callee_task(phone); |
296 | ta = get_lock_callee_task(phone); |
302 | spinlock_unlock(&ta->lock); |
297 | spinlock_unlock(&ta->lock); |
303 | //FIXME: don't lock ta |
298 | //FIXME: don't lock ta |
304 | 299 | ||
305 | ipl = interrupts_disable(); |
300 | ipl = interrupts_disable(); |
306 | spinlock_lock(&threads_lock); |
301 | spinlock_lock(&threads_lock); |
307 | 302 | ||
308 | t = (thread_t *) IPC_GET_ARG2(call->data); |
303 | t = (thread_t *) IPC_GET_ARG2(call->data); |
309 | 304 | ||
310 | /* Verify that 't' exists and belongs to task 'ta' */ |
305 | /* Verify that 't' exists and belongs to task 'ta' */ |
311 | if (!thread_exists(t) || (t->task != ta)) { |
306 | if (!thread_exists(t) || (t->task != ta)) { |
312 | spinlock_unlock(&threads_lock); |
307 | spinlock_unlock(&threads_lock); |
313 | interrupts_restore(ipl); |
308 | interrupts_restore(ipl); |
314 | return ENOENT; |
309 | return ENOENT; |
315 | } |
310 | } |
316 | 311 | ||
317 | if ((t->debug_active != true) || (t->debug_stop != true)) { |
312 | if ((t->debug_active != true) || (t->debug_stop != true)) { |
318 | /* Not in debugging session or has GO */ |
313 | /* Not in debugging session or has GO */ |
319 | spinlock_unlock(&threads_lock); |
314 | spinlock_unlock(&threads_lock); |
320 | interrupts_restore(ipl); |
315 | interrupts_restore(ipl); |
321 | return EBUSY; |
316 | return EBUSY; |
322 | } |
317 | } |
323 | 318 | ||
324 | state = t->uspace_state; |
319 | state = t->uspace_state; |
325 | if (state == NULL) { |
320 | if (state == NULL) { |
326 | spinlock_unlock(&threads_lock); |
321 | spinlock_unlock(&threads_lock); |
327 | interrupts_restore(ipl); |
322 | interrupts_restore(ipl); |
328 | klog_printf("debug_regs_read() - istate not available"); |
323 | klog_printf("debug_regs_read() - istate not available"); |
329 | return EBUSY; |
324 | return EBUSY; |
330 | } |
325 | } |
331 | 326 | ||
332 | /* Copy to a local buffer so that we can release the lock */ |
327 | /* Copy to a local buffer so that we can release the lock */ |
333 | memcpy(&state_copy, state, sizeof(state_copy)); |
328 | memcpy(&state_copy, state, sizeof(state_copy)); |
334 | spinlock_unlock(&threads_lock); |
329 | spinlock_unlock(&threads_lock); |
335 | interrupts_restore(ipl); |
330 | interrupts_restore(ipl); |
336 | 331 | ||
337 | uspace_buffer = (void *)IPC_GET_ARG3(call->data); |
332 | uspace_buffer = (void *)IPC_GET_ARG3(call->data); |
338 | to_copy = IPC_GET_ARG4(call->data); |
333 | to_copy = IPC_GET_ARG4(call->data); |
339 | if (to_copy > sizeof(istate_t)) to_copy = sizeof(istate_t); |
334 | if (to_copy > sizeof(istate_t)) to_copy = sizeof(istate_t); |
340 | 335 | ||
341 | rc = copy_to_uspace(uspace_buffer, &state_copy, to_copy); |
336 | rc = copy_to_uspace(uspace_buffer, &state_copy, to_copy); |
342 | if (rc != 0) { |
337 | if (rc != 0) { |
343 | spinlock_unlock(&ta->lock); |
338 | spinlock_unlock(&ta->lock); |
344 | klog_printf("debug_regs_read() - copy failed"); |
339 | klog_printf("debug_regs_read() - copy failed"); |
345 | return rc; |
340 | return rc; |
346 | } |
341 | } |
347 | 342 | ||
348 | IPC_SET_ARG1(call->data, to_copy); |
343 | IPC_SET_ARG1(call->data, to_copy); |
349 | IPC_SET_ARG2(call->data, sizeof(istate_t)); |
344 | IPC_SET_ARG2(call->data, sizeof(istate_t)); |
350 | 345 | ||
351 | klog_printf("debug_regs_read() done"); |
346 | klog_printf("debug_regs_read() done"); |
352 | return 1; /* actually need becksend with retval 0 */ |
347 | return 1; /* actually need becksend with retval 0 */ |
353 | } |
348 | } |
354 | 349 | ||
355 | static int udebug_rp_regs_write(call_t *call, phone_t *phone) |
350 | static int udebug_rp_regs_write(call_t *call, phone_t *phone) |
356 | { |
351 | { |
357 | thread_t *t; |
352 | thread_t *t; |
358 | task_t *ta; |
353 | task_t *ta; |
359 | void *uspace_data; |
354 | void *uspace_data; |
360 | unative_t to_copy; |
355 | unative_t to_copy; |
361 | int rc; |
356 | int rc; |
362 | istate_t *state; |
357 | istate_t *state; |
363 | istate_t data_copy; |
358 | istate_t data_copy; |
364 | ipl_t ipl; |
359 | ipl_t ipl; |
365 | 360 | ||
366 | klog_printf("debug_regs_write()"); |
361 | klog_printf("debug_regs_write()"); |
367 | 362 | ||
368 | /* First copy to a local buffer */ |
363 | /* First copy to a local buffer */ |
369 | 364 | ||
370 | uspace_data = (void *)IPC_GET_ARG3(call->data); |
365 | uspace_data = (void *)IPC_GET_ARG3(call->data); |
371 | to_copy = IPC_GET_ARG4(call->data); |
366 | to_copy = IPC_GET_ARG4(call->data); |
372 | if (to_copy > sizeof(istate_t)) to_copy = sizeof(istate_t); |
367 | if (to_copy > sizeof(istate_t)) to_copy = sizeof(istate_t); |
373 | 368 | ||
374 | rc = copy_from_uspace(&data_copy, uspace_data, to_copy); |
369 | rc = copy_from_uspace(&data_copy, uspace_data, to_copy); |
375 | if (rc != 0) { |
370 | if (rc != 0) { |
376 | klog_printf("debug_regs_write() - copy failed"); |
371 | klog_printf("debug_regs_write() - copy failed"); |
377 | return rc; |
372 | return rc; |
378 | } |
373 | } |
379 | 374 | ||
380 | ta = get_lock_callee_task(phone); |
375 | ta = get_lock_callee_task(phone); |
381 | spinlock_unlock(&ta->lock); |
376 | spinlock_unlock(&ta->lock); |
382 | //FIXME: don't lock ta |
377 | //FIXME: don't lock ta |
383 | 378 | ||
384 | /* Now try to change the thread's uspace_state */ |
379 | /* Now try to change the thread's uspace_state */ |
385 | 380 | ||
386 | ipl = interrupts_disable(); |
381 | ipl = interrupts_disable(); |
387 | spinlock_lock(&threads_lock); |
382 | spinlock_lock(&threads_lock); |
388 | 383 | ||
389 | t = (thread_t *) IPC_GET_ARG2(call->data); |
384 | t = (thread_t *) IPC_GET_ARG2(call->data); |
390 | 385 | ||
391 | /* Verify that 't' exists and belongs to task 'ta' */ |
386 | /* Verify that 't' exists and belongs to task 'ta' */ |
392 | if (!thread_exists(t) || (t->task != ta)) { |
387 | if (!thread_exists(t) || (t->task != ta)) { |
393 | spinlock_unlock(&threads_lock); |
388 | spinlock_unlock(&threads_lock); |
394 | interrupts_restore(ipl); |
389 | interrupts_restore(ipl); |
395 | return ENOENT; |
390 | return ENOENT; |
396 | } |
391 | } |
397 | 392 | ||
398 | if ((t->debug_active != true) || (t->debug_stop != true)) { |
393 | if ((t->debug_active != true) || (t->debug_stop != true)) { |
399 | /* Not in debugging session or has GO */ |
394 | /* Not in debugging session or has GO */ |
400 | spinlock_unlock(&threads_lock); |
395 | spinlock_unlock(&threads_lock); |
401 | interrupts_restore(ipl); |
396 | interrupts_restore(ipl); |
402 | return EBUSY; |
397 | return EBUSY; |
403 | } |
398 | } |
404 | 399 | ||
405 | state = t->uspace_state; |
400 | state = t->uspace_state; |
406 | if (state == NULL) { |
401 | if (state == NULL) { |
407 | spinlock_unlock(&threads_lock); |
402 | spinlock_unlock(&threads_lock); |
408 | interrupts_restore(ipl); |
403 | interrupts_restore(ipl); |
409 | klog_printf("debug_regs_write() - istate not available"); |
404 | klog_printf("debug_regs_write() - istate not available"); |
410 | return EBUSY; |
405 | return EBUSY; |
411 | } |
406 | } |
412 | 407 | ||
413 | memcpy(t->uspace_state, &data_copy, sizeof(t->uspace_state)); |
408 | memcpy(t->uspace_state, &data_copy, sizeof(t->uspace_state)); |
414 | 409 | ||
415 | spinlock_unlock(&threads_lock); |
410 | spinlock_unlock(&threads_lock); |
416 | interrupts_restore(ipl); |
411 | interrupts_restore(ipl); |
417 | 412 | ||
418 | /* Set answer values */ |
413 | /* Set answer values */ |
419 | 414 | ||
420 | IPC_SET_ARG1(call->data, to_copy); |
415 | IPC_SET_ARG1(call->data, to_copy); |
421 | IPC_SET_ARG2(call->data, sizeof(istate_t)); |
416 | IPC_SET_ARG2(call->data, sizeof(istate_t)); |
422 | 417 | ||
423 | klog_printf("debug_regs_write() done"); |
418 | klog_printf("debug_regs_write() done"); |
424 | return 1; /* actually need becksend with retval 0 */ |
419 | return 1; /* actually need becksend with retval 0 */ |
425 | } |
420 | } |
426 | 421 | ||
427 | static int udebug_rp_thread_read(call_t *call, phone_t *phone) |
422 | static int udebug_rp_thread_read(call_t *call, phone_t *phone) |
428 | { |
423 | { |
429 | thread_t *t; |
424 | thread_t *t; |
430 | link_t *cur; |
425 | link_t *cur; |
431 | task_t *ta; |
426 | task_t *ta; |
432 | unative_t *uspace_buffer; |
427 | unative_t *uspace_buffer; |
433 | unative_t to_copy; |
428 | unative_t to_copy; |
434 | int rc; |
429 | int rc; |
435 | unsigned total_bytes; |
430 | unsigned total_bytes; |
436 | unsigned buf_size; |
431 | unsigned buf_size; |
437 | unative_t tid; |
432 | unative_t tid; |
438 | unsigned num_threads, copied_ids; |
433 | unsigned num_threads, copied_ids; |
439 | ipl_t ipl; |
434 | ipl_t ipl; |
440 | unative_t *buffer; |
435 | unative_t *buffer; |
441 | int flags; |
436 | int flags; |
442 | 437 | ||
443 | klog_printf("debug_thread_read()"); |
438 | klog_printf("debug_thread_read()"); |
444 | 439 | ||
445 | ipl = interrupts_disable(); |
440 | ipl = interrupts_disable(); |
446 | ta = get_lock_callee_task(phone); |
441 | ta = get_lock_callee_task(phone); |
447 | 442 | ||
448 | /* Verify task state */ |
443 | /* Verify task state */ |
449 | if (ta->dt_state != UDEBUG_TS_ACTIVE) { |
444 | if (ta->dt_state != UDEBUG_TS_ACTIVE) { |
450 | spinlock_unlock(&ta->lock); |
445 | spinlock_unlock(&ta->lock); |
451 | interrupts_restore(ipl); |
446 | interrupts_restore(ipl); |
452 | return EBUSY; |
447 | return EBUSY; |
453 | } |
448 | } |
454 | 449 | ||
455 | /* Count the threads first */ |
450 | /* Count the threads first */ |
456 | 451 | ||
457 | num_threads = 0; |
452 | num_threads = 0; |
458 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
453 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
459 | /* Count all threads, to be on the safe side */ |
454 | /* Count all threads, to be on the safe side */ |
460 | ++num_threads; |
455 | ++num_threads; |
461 | } |
456 | } |
462 | 457 | ||
463 | /* Allocate a buffer and copy down the threads' ids */ |
458 | /* Allocate a buffer and copy down the threads' ids */ |
464 | buffer = malloc(num_threads * sizeof(unative_t), 0); // ??? |
459 | buffer = malloc(num_threads * sizeof(unative_t), 0); // ??? |
465 | 460 | ||
466 | copied_ids = 0; |
461 | copied_ids = 0; |
467 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
462 | for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) { |
468 | t = list_get_instance(cur, thread_t, th_link); |
463 | t = list_get_instance(cur, thread_t, th_link); |
469 | 464 | ||
470 | spinlock_lock(&t->lock); |
465 | spinlock_lock(&t->lock); |
471 | flags = t->flags; |
466 | flags = t->flags; |
472 | spinlock_unlock(&t->lock); |
467 | spinlock_unlock(&t->lock); |
473 | 468 | ||
474 | /* Not interested in kernel threads */ |
469 | /* Not interested in kernel threads */ |
475 | if ((flags & THREAD_FLAG_USPACE) != 0) { |
470 | if ((flags & THREAD_FLAG_USPACE) != 0) { |
476 | /* Using thread struct pointer for identification */ |
471 | /* Using thread struct pointer for identification */ |
477 | tid = (unative_t) t; |
472 | tid = (unative_t) t; |
478 | buffer[copied_ids++] = tid; |
473 | buffer[copied_ids++] = tid; |
479 | } |
474 | } |
480 | } |
475 | } |
481 | 476 | ||
482 | spinlock_unlock(&ta->lock); |
477 | spinlock_unlock(&ta->lock); |
483 | interrupts_restore(ipl); |
478 | interrupts_restore(ipl); |
484 | 479 | ||
485 | /* Now copy to userspace */ |
480 | /* Now copy to userspace */ |
486 | 481 | ||
487 | uspace_buffer = (void *)IPC_GET_ARG2(call->data); |
482 | uspace_buffer = (void *)IPC_GET_ARG2(call->data); |
488 | buf_size = IPC_GET_ARG3(call->data); |
483 | buf_size = IPC_GET_ARG3(call->data); |
489 | 484 | ||
490 | total_bytes = copied_ids * sizeof(unative_t); |
485 | total_bytes = copied_ids * sizeof(unative_t); |
491 | 486 | ||
492 | if (buf_size > total_bytes) |
487 | if (buf_size > total_bytes) |
493 | to_copy = total_bytes; |
488 | to_copy = total_bytes; |
494 | else |
489 | else |
495 | to_copy = buf_size; |
490 | to_copy = buf_size; |
496 | 491 | ||
497 | rc = copy_to_uspace(uspace_buffer, buffer, to_copy); |
492 | rc = copy_to_uspace(uspace_buffer, buffer, to_copy); |
498 | free(buffer); |
493 | free(buffer); |
499 | 494 | ||
500 | if (rc != 0) { |
495 | if (rc != 0) { |
501 | klog_printf("debug_thread_read() - copy failed"); |
496 | klog_printf("debug_thread_read() - copy failed"); |
502 | return rc; |
497 | return rc; |
503 | } |
498 | } |
504 | 499 | ||
505 | IPC_SET_ARG1(call->data, to_copy); |
500 | IPC_SET_ARG1(call->data, to_copy); |
506 | IPC_SET_ARG2(call->data, total_bytes); |
501 | IPC_SET_ARG2(call->data, total_bytes); |
507 | 502 | ||
508 | klog_printf("debug_thread_read() done"); |
503 | klog_printf("debug_thread_read() done"); |
509 | return 1; /* actually need becksend with retval 0 */ |
504 | return 1; /* actually need becksend with retval 0 */ |
510 | } |
505 | } |
511 | 506 | ||
512 | static int udebug_rp_mem_write(call_t *call, phone_t *phone) |
507 | static int udebug_rp_mem_write(call_t *call, phone_t *phone) |
513 | { |
508 | { |
514 | void *uspace_data; |
509 | void *uspace_data; |
515 | unative_t to_copy; |
510 | unative_t to_copy; |
516 | int rc; |
511 | int rc; |
517 | void *buffer; |
512 | void *buffer; |
518 | 513 | ||
519 | klog_printf("udebug_rp_mem_write()"); |
514 | klog_printf("udebug_rp_mem_write()"); |
520 | 515 | ||
521 | uspace_data = (void *)IPC_GET_ARG2(call->data); |
516 | uspace_data = (void *)IPC_GET_ARG2(call->data); |
522 | to_copy = IPC_GET_ARG4(call->data); |
517 | to_copy = IPC_GET_ARG4(call->data); |
523 | 518 | ||
524 | buffer = malloc(to_copy, 0); // ??? |
519 | buffer = malloc(to_copy, 0); // ??? |
525 | 520 | ||
526 | rc = copy_from_uspace(buffer, uspace_data, to_copy); |
521 | rc = copy_from_uspace(buffer, uspace_data, to_copy); |
527 | if (rc != 0) { |
522 | if (rc != 0) { |
528 | klog_printf(" - copy failed"); |
523 | klog_printf(" - copy failed"); |
529 | return rc; |
524 | return rc; |
530 | } |
525 | } |
531 | 526 | ||
532 | call->buffer = buffer; |
527 | call->buffer = buffer; |
533 | 528 | ||
534 | klog_printf(" - done"); |
529 | klog_printf(" - done"); |
535 | return 1; /* actually need becksend with retval 0 */ |
530 | return 1; /* actually need becksend with retval 0 */ |
536 | } |
531 | } |
537 | 532 | ||
538 | 533 | ||
539 | int udebug_request_preprocess(call_t *call, phone_t *phone) |
534 | int udebug_request_preprocess(call_t *call, phone_t *phone) |
540 | { |
535 | { |
541 | int rc; |
536 | int rc; |
542 | 537 | ||
543 | switch (IPC_GET_ARG1(call->data)) { |
538 | switch (IPC_GET_ARG1(call->data)) { |
544 | case UDEBUG_M_BEGIN: |
539 | case UDEBUG_M_BEGIN: |
545 | rc = udebug_rp_begin(call, phone); |
540 | rc = udebug_rp_begin(call, phone); |
546 | return rc; |
541 | return rc; |
547 | case UDEBUG_M_END: |
542 | case UDEBUG_M_END: |
548 | rc = udebug_rp_end(call, phone); |
543 | rc = udebug_rp_end(call, phone); |
549 | return rc; |
544 | return rc; |
550 | case UDEBUG_M_GO: |
545 | case UDEBUG_M_GO: |
551 | rc = udebug_rp_go(call, phone); |
546 | rc = udebug_rp_go(call, phone); |
552 | return rc; |
547 | return rc; |
553 | case UDEBUG_M_ARGS_READ: |
548 | case UDEBUG_M_ARGS_READ: |
554 | rc = udebug_rp_args_read(call, phone); |
549 | rc = udebug_rp_args_read(call, phone); |
555 | return rc; |
550 | return rc; |
556 | case UDEBUG_M_REGS_READ: |
551 | case UDEBUG_M_REGS_READ: |
557 | rc = udebug_rp_regs_read(call, phone); |
552 | rc = udebug_rp_regs_read(call, phone); |
558 | return rc; |
553 | return rc; |
559 | case UDEBUG_M_REGS_WRITE: |
554 | case UDEBUG_M_REGS_WRITE: |
560 | rc = udebug_rp_regs_write(call, phone); |
555 | rc = udebug_rp_regs_write(call, phone); |
561 | return rc; |
556 | return rc; |
562 | case UDEBUG_M_THREAD_READ: |
557 | case UDEBUG_M_THREAD_READ: |
563 | rc = udebug_rp_thread_read(call, phone); |
558 | rc = udebug_rp_thread_read(call, phone); |
564 | return rc; |
559 | return rc; |
565 | case UDEBUG_M_MEM_WRITE: |
560 | case UDEBUG_M_MEM_WRITE: |
566 | rc = udebug_rp_mem_write(call, phone); |
561 | rc = udebug_rp_mem_write(call, phone); |
567 | return rc; |
562 | return rc; |
568 | default: |
563 | default: |
569 | break; |
564 | break; |
570 | } |
565 | } |
571 | 566 | ||
572 | return 0; |
567 | return 0; |
573 | } |
568 | } |
574 | 569 | ||
575 | static void udebug_receive_mem_read(call_t *call) |
570 | static void udebug_receive_mem_read(call_t *call) |
576 | { |
571 | { |
577 | unative_t uspace_dst; |
572 | unative_t uspace_dst; |
578 | void *uspace_ptr; |
573 | void *uspace_ptr; |
579 | unsigned size; |
574 | unsigned size; |
580 | void *buffer; |
575 | void *buffer; |
581 | int rc; |
576 | int rc; |
582 | 577 | ||
583 | klog_printf("debug_mem_read()"); |
578 | klog_printf("debug_mem_read()"); |
584 | uspace_dst = IPC_GET_ARG2(call->data); |
579 | uspace_dst = IPC_GET_ARG2(call->data); |
585 | uspace_ptr = (void *)IPC_GET_ARG3(call->data); |
580 | uspace_ptr = (void *)IPC_GET_ARG3(call->data); |
586 | size = IPC_GET_ARG4(call->data); |
581 | size = IPC_GET_ARG4(call->data); |
587 | 582 | ||
588 | buffer = malloc(size, 0); // ??? |
583 | buffer = malloc(size, 0); // ??? |
589 | klog_printf("debug_mem_read: src=%u, size=%u", uspace_ptr, size); |
584 | klog_printf("debug_mem_read: src=%u, size=%u", uspace_ptr, size); |
590 | 585 | ||
591 | /* NOTE: this is not strictly from a syscall... but that shouldn't |
586 | /* NOTE: this is not strictly from a syscall... but that shouldn't |
592 | * be a problem */ |
587 | * be a problem */ |
593 | rc = copy_from_uspace(buffer, uspace_ptr, size); |
588 | rc = copy_from_uspace(buffer, uspace_ptr, size); |
594 | if (rc) { |
589 | if (rc) { |
595 | IPC_SET_RETVAL(call->data, rc); |
590 | IPC_SET_RETVAL(call->data, rc); |
596 | return; |
591 | return; |
597 | } |
592 | } |
598 | 593 | ||
599 | klog_printf("first word: %u", *((unative_t *)buffer)); |
594 | klog_printf("first word: %u", *((unative_t *)buffer)); |
600 | 595 | ||
601 | IPC_SET_RETVAL(call->data, 0); |
596 | IPC_SET_RETVAL(call->data, 0); |
602 | /* Hack: ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that |
597 | /* Hack: ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that |
603 | same code in process_answer() can be used |
598 | same code in process_answer() can be used |
604 | (no way to distinguish method in answer) */ |
599 | (no way to distinguish method in answer) */ |
605 | IPC_SET_ARG1(call->data, uspace_dst); |
600 | IPC_SET_ARG1(call->data, uspace_dst); |
606 | IPC_SET_ARG2(call->data, size); |
601 | IPC_SET_ARG2(call->data, size); |
607 | call->buffer = buffer; |
602 | call->buffer = buffer; |
608 | 603 | ||
609 | ipc_answer(&TASK->kernel_box, call); |
604 | ipc_answer(&TASK->kernel_box, call); |
610 | } |
605 | } |
611 | 606 | ||
612 | static void udebug_receive_mem_write(call_t *call) |
607 | static void udebug_receive_mem_write(call_t *call) |
613 | { |
608 | { |
614 | void *uspace_dst; |
609 | void *uspace_dst; |
615 | unsigned size; |
610 | unsigned size; |
616 | void *buffer; |
611 | void *buffer; |
617 | int rc; |
612 | int rc; |
618 | udebug_task_state_t dts; |
613 | udebug_task_state_t dts; |
619 | 614 | ||
620 | klog_printf("udebug_receive_mem_write()"); |
615 | klog_printf("udebug_receive_mem_write()"); |
621 | 616 | ||
622 | /* Verify task state */ |
617 | /* Verify task state */ |
623 | spinlock_lock(&TASK->lock); |
618 | spinlock_lock(&TASK->lock); |
624 | dts = TASK->dt_state; |
619 | dts = TASK->dt_state; |
625 | spinlock_unlock(&TASK->lock); |
620 | spinlock_unlock(&TASK->lock); |
626 | 621 | ||
627 | if (dts != UDEBUG_TS_ACTIVE) { |
622 | if (dts != UDEBUG_TS_ACTIVE) { |
628 | IPC_SET_RETVAL(call->data, EBUSY); |
623 | IPC_SET_RETVAL(call->data, EBUSY); |
629 | ipc_answer(&TASK->kernel_box, call); |
624 | ipc_answer(&TASK->kernel_box, call); |
630 | return; |
625 | return; |
631 | } |
626 | } |
632 | 627 | ||
633 | uspace_dst = (void *)IPC_GET_ARG3(call->data); |
628 | uspace_dst = (void *)IPC_GET_ARG3(call->data); |
634 | size = IPC_GET_ARG4(call->data); |
629 | size = IPC_GET_ARG4(call->data); |
635 | 630 | ||
636 | buffer = call->buffer; |
631 | buffer = call->buffer; |
637 | klog_printf("dst=%u, size=%u", uspace_dst, size); |
632 | klog_printf("dst=%u, size=%u", uspace_dst, size); |
638 | 633 | ||
639 | /* NOTE: this is not strictly from a syscall... but that shouldn't |
634 | /* NOTE: this is not strictly from a syscall... but that shouldn't |
640 | * be a problem */ |
635 | * be a problem */ |
641 | rc = copy_to_uspace(uspace_dst, buffer, size); |
636 | rc = copy_to_uspace(uspace_dst, buffer, size); |
642 | if (rc) { |
637 | if (rc) { |
643 | IPC_SET_RETVAL(call->data, rc); |
638 | IPC_SET_RETVAL(call->data, rc); |
644 | ipc_answer(&TASK->kernel_box, call); |
639 | ipc_answer(&TASK->kernel_box, call); |
645 | return; |
640 | return; |
646 | } |
641 | } |
647 | 642 | ||
648 | IPC_SET_RETVAL(call->data, 0); |
643 | IPC_SET_RETVAL(call->data, 0); |
649 | 644 | ||
650 | free(call->buffer); |
645 | free(call->buffer); |
651 | call->buffer = NULL; |
646 | call->buffer = NULL; |
652 | 647 | ||
653 | ipc_answer(&TASK->kernel_box, call); |
648 | ipc_answer(&TASK->kernel_box, call); |
654 | } |
649 | } |
655 | 650 | ||
656 | 651 | ||
657 | /** |
652 | /** |
658 | * Handle a debug call received on the kernel answerbox. |
653 | * Handle a debug call received on the kernel answerbox. |
659 | * |
654 | * |
660 | * This is called by the kbox servicing thread. |
655 | * This is called by the kbox servicing thread. |
661 | */ |
656 | */ |
662 | void udebug_call_receive(call_t *call) |
657 | void udebug_call_receive(call_t *call) |
663 | { |
658 | { |
664 | int debug_method; |
659 | int debug_method; |
665 | 660 | ||
666 | debug_method = IPC_GET_ARG1(call->data); |
661 | debug_method = IPC_GET_ARG1(call->data); |
667 | 662 | ||
668 | switch (debug_method) { |
663 | switch (debug_method) { |
669 | case UDEBUG_M_MEM_READ: |
664 | case UDEBUG_M_MEM_READ: |
670 | udebug_receive_mem_read(call); |
665 | udebug_receive_mem_read(call); |
671 | break; |
666 | break; |
672 | case UDEBUG_M_MEM_WRITE: |
667 | case UDEBUG_M_MEM_WRITE: |
673 | udebug_receive_mem_write(call); |
668 | udebug_receive_mem_write(call); |
674 | break; |
669 | break; |
675 | } |
670 | } |
676 | } |
671 | } |
677 | 672 | ||
678 | /** @} |
673 | /** @} |
679 | */ |
674 | */ |
680 | 675 |