Subversion Repositories HelenOS

Rev

Rev 2848 | Rev 2851 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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