Subversion Repositories HelenOS

Rev

Rev 2833 | Rev 2835 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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