Subversion Repositories HelenOS

Rev

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

Rev Author Line No. Line
2894 svoboda 1
/*
2
 * Copyright (c) 2008 Jiri Svoboda
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
28
 
2813 svoboda 29
/** @addtogroup generic
30
 * @{
31
 */
32
 
33
/**
34
 * @file
2894 svoboda 35
 * @brief   Udebug IPC message handling.
2813 svoboda 36
 */
37
 
38
#include <console/klog.h>
39
#include <proc/task.h>
40
#include <proc/thread.h>
2815 svoboda 41
#include <arch.h>
2813 svoboda 42
#include <errno.h>
43
#include <ipc/ipc.h>
44
#include <syscall/copy.h>
45
#include <udebug/udebug.h>
2887 svoboda 46
#include <udebug/udebug_ops.h>
2813 svoboda 47
#include <udebug/udebug_ipc.h>
48
 
2817 svoboda 49
static int udebug_rp_regs_write(call_t *call, phone_t *phone)
50
{
51
    void *uspace_data;
52
    unative_t to_copy;
53
    int rc;
2886 svoboda 54
    void *buffer;
2817 svoboda 55
 
56
    klog_printf("debug_regs_write()");
57
 
58
    uspace_data = (void *)IPC_GET_ARG3(call->data);
59
    to_copy = IPC_GET_ARG4(call->data);
60
    if (to_copy > sizeof(istate_t)) to_copy = sizeof(istate_t);
61
 
2886 svoboda 62
    buffer = malloc(to_copy, 0); // ??? 
63
 
64
    rc = copy_from_uspace(buffer, uspace_data, to_copy);
2817 svoboda 65
    if (rc != 0) {
66
        klog_printf("debug_regs_write() - copy failed");
67
        return rc;
68
    }
69
 
2886 svoboda 70
    call->buffer = buffer;
2824 svoboda 71
 
2886 svoboda 72
    klog_printf(" - done");
2892 svoboda 73
    return 0;
2817 svoboda 74
}
75
 
2885 svoboda 76
static int udebug_rp_mem_write(call_t *call, phone_t *phone)
2813 svoboda 77
{
2885 svoboda 78
    void *uspace_data;
79
    unative_t to_copy;
80
    int rc;
81
    void *buffer;
82
 
83
    klog_printf("udebug_rp_mem_write()");
84
 
85
    uspace_data = (void *)IPC_GET_ARG2(call->data);
86
    to_copy = IPC_GET_ARG4(call->data);
87
 
88
    buffer = malloc(to_copy, 0); // ???
89
 
90
    rc = copy_from_uspace(buffer, uspace_data, to_copy);
91
    if (rc != 0) {
92
        klog_printf(" - copy failed");
93
        return rc;
94
    }
95
 
96
    call->buffer = buffer;
97
 
98
    klog_printf(" - done");
2892 svoboda 99
    return 0;
2885 svoboda 100
}
101
 
102
 
103
int udebug_request_preprocess(call_t *call, phone_t *phone)
104
{
105
    int rc;
106
 
107
    switch (IPC_GET_ARG1(call->data)) {
108
    case UDEBUG_M_REGS_WRITE:
109
        rc = udebug_rp_regs_write(call, phone);
110
        return rc;
111
    case UDEBUG_M_MEM_WRITE:
112
        rc = udebug_rp_mem_write(call, phone);
113
        return rc;
114
    default:
115
        break;
116
    }
117
 
118
    return 0;
119
}
120
 
121
static void udebug_receive_begin(call_t *call)
122
{
2887 svoboda 123
    int rc;
2885 svoboda 124
 
2887 svoboda 125
    rc = udebug_begin(call);
126
    if (rc < 0) {
127
        IPC_SET_RETVAL(call->data, rc);
2885 svoboda 128
        ipc_answer(&TASK->kernel_box, call);
2887 svoboda 129
        return;
2885 svoboda 130
    }
131
 
2887 svoboda 132
    if (rc != 0) {
133
        IPC_SET_RETVAL(call->data, 0);
134
        ipc_answer(&TASK->kernel_box, call);
2885 svoboda 135
    }
136
}
137
 
138
static void udebug_receive_end(call_t *call)
139
{
140
    int rc;
141
 
2887 svoboda 142
    rc = udebug_end();
2885 svoboda 143
 
2887 svoboda 144
    IPC_SET_RETVAL(call->data, rc);
2885 svoboda 145
    ipc_answer(&TASK->kernel_box, call);
146
}
147
 
2886 svoboda 148
static void udebug_receive_go(call_t *call)
149
{
150
    thread_t *t;
151
    int rc;
152
 
153
    klog_printf("debug_go()");
154
 
155
    t = (thread_t *)IPC_GET_ARG2(call->data);
156
 
2887 svoboda 157
    rc = udebug_go(t, call);
158
    if (rc < 0) {
2886 svoboda 159
        IPC_SET_RETVAL(call->data, rc);
160
        ipc_answer(&TASK->kernel_box, call);
161
        return;
162
    }
163
}
164
 
165
 
2885 svoboda 166
static void udebug_receive_thread_read(call_t *call)
167
{
168
    unative_t uspace_addr;
2813 svoboda 169
    unative_t to_copy;
2824 svoboda 170
    unsigned total_bytes;
2813 svoboda 171
    unsigned buf_size;
2887 svoboda 172
    void *buffer;
173
    size_t n;
174
    int rc;
2813 svoboda 175
 
2887 svoboda 176
    rc = udebug_thread_read(&buffer, &n);
177
    if (rc < 0) {
178
        IPC_SET_RETVAL(call->data, rc);
2885 svoboda 179
        ipc_answer(&TASK->kernel_box, call);
180
        return;
2827 svoboda 181
    }
182
 
2885 svoboda 183
    /*
2887 svoboda 184
     * Make use of call->buffer to transfer data to caller's userspace
2885 svoboda 185
     */
2813 svoboda 186
 
2885 svoboda 187
    uspace_addr = IPC_GET_ARG2(call->data);
2824 svoboda 188
    buf_size = IPC_GET_ARG3(call->data);
2813 svoboda 189
 
2887 svoboda 190
    total_bytes = n;
2824 svoboda 191
 
192
    if (buf_size > total_bytes)
193
        to_copy = total_bytes;
194
    else
195
        to_copy = buf_size;
196
 
2885 svoboda 197
    IPC_SET_RETVAL(call->data, 0);
198
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
199
       same code in process_answer() can be used
200
       (no way to distinguish method in answer) */
201
    IPC_SET_ARG1(call->data, uspace_addr);
202
    IPC_SET_ARG2(call->data, to_copy);
2824 svoboda 203
 
2885 svoboda 204
    IPC_SET_ARG3(call->data, total_bytes);
2887 svoboda 205
    call->buffer = buffer;
2813 svoboda 206
 
2885 svoboda 207
    ipc_answer(&TASK->kernel_box, call);
2813 svoboda 208
}
209
 
2886 svoboda 210
static void udebug_receive_args_read(call_t *call)
211
{
212
    thread_t *t;
213
    unative_t uspace_addr;
214
    int rc;
2887 svoboda 215
    void *buffer;
2818 svoboda 216
 
2886 svoboda 217
    t = (thread_t *)IPC_GET_ARG2(call->data);
218
 
2887 svoboda 219
    rc = udebug_args_read(t, &buffer);
2886 svoboda 220
    if (rc != EOK) {
221
        IPC_SET_RETVAL(call->data, rc);
222
        ipc_answer(&TASK->kernel_box, call);
223
        return;
224
    }
225
 
226
    /*
227
     * Make use of call->buffer to transfer data to caller's userspace
228
     */
229
 
230
    uspace_addr = IPC_GET_ARG3(call->data);
231
 
232
    IPC_SET_RETVAL(call->data, 0);
233
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
234
       same code in process_answer() can be used
235
       (no way to distinguish method in answer) */
236
    IPC_SET_ARG1(call->data, uspace_addr);
237
    IPC_SET_ARG2(call->data, 6 * sizeof(unative_t));
2887 svoboda 238
    call->buffer = buffer;
2886 svoboda 239
 
240
    ipc_answer(&TASK->kernel_box, call);
241
}
242
 
243
static void udebug_receive_regs_read(call_t *call)
244
{
245
    thread_t *t;
246
    unative_t uspace_addr;
247
    unative_t to_copy;
248
    unative_t buf_size;
249
    unative_t total_bytes;
250
    void *buffer;
251
    int rc;
2887 svoboda 252
    size_t n;
2886 svoboda 253
 
254
    klog_printf("debug_regs_read()");
255
 
256
    t = (thread_t *) IPC_GET_ARG2(call->data);
257
 
2887 svoboda 258
    rc = udebug_regs_read(t, &buffer, &n);
259
    if (rc < 0) {
2886 svoboda 260
        IPC_SET_RETVAL(call->data, rc);
261
        ipc_answer(&TASK->kernel_box, call);
262
        return;
263
    }
264
 
265
    /*
266
     * Make use of call->buffer to transfer data to caller's userspace
267
     */
268
 
269
    uspace_addr = IPC_GET_ARG3(call->data);
270
    buf_size = IPC_GET_ARG4(call->data);
271
 
2887 svoboda 272
    total_bytes = n;
2886 svoboda 273
 
274
    if (buf_size > total_bytes)
275
        to_copy = total_bytes;
276
    else
277
        to_copy = buf_size;
278
 
279
    IPC_SET_RETVAL(call->data, 0);
280
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
281
       same code in process_answer() can be used
282
       (no way to distinguish method in answer) */
283
    IPC_SET_ARG1(call->data, uspace_addr);
284
    IPC_SET_ARG2(call->data, to_copy);
285
 
286
    IPC_SET_ARG3(call->data, total_bytes);
2887 svoboda 287
    call->buffer = buffer;
2886 svoboda 288
 
289
    ipc_answer(&TASK->kernel_box, call);
290
}
291
 
292
static void udebug_receive_regs_write(call_t *call)
293
{
294
    thread_t *t;
295
    void *uspace_data;
296
    unative_t to_copy;
297
    int rc;
298
 
299
    uspace_data = (void *)IPC_GET_ARG3(call->data);
300
    to_copy = IPC_GET_ARG4(call->data);
301
 
302
    t = (thread_t *) IPC_GET_ARG2(call->data);
303
 
2887 svoboda 304
    rc = udebug_regs_write(t, call->buffer);
305
    if (rc < 0) {
2886 svoboda 306
        IPC_SET_RETVAL(call->data, rc);
307
        ipc_answer(&TASK->kernel_box, call);
308
        return;
309
    }
310
 
311
    /* Set answer values */
312
 
313
    IPC_SET_ARG1(call->data, to_copy);
314
    IPC_SET_ARG2(call->data, sizeof(istate_t));
315
 
316
    IPC_SET_RETVAL(call->data, 0);
2887 svoboda 317
    free(call->buffer);
318
    call->buffer = NULL;
319
 
2886 svoboda 320
    ipc_answer(&TASK->kernel_box, call);
321
}
322
 
323
 
2815 svoboda 324
static void udebug_receive_mem_read(call_t *call)
325
{
326
    unative_t uspace_dst;
2887 svoboda 327
    unative_t uspace_src;
2815 svoboda 328
    unsigned size;
329
    void *buffer;
330
    int rc;
2813 svoboda 331
 
2815 svoboda 332
    uspace_dst = IPC_GET_ARG2(call->data);
2887 svoboda 333
    uspace_src = IPC_GET_ARG3(call->data);
2815 svoboda 334
    size = IPC_GET_ARG4(call->data);
335
 
2887 svoboda 336
    rc = udebug_mem_read(uspace_src, size, &buffer);
337
    if (rc < 0) {
2815 svoboda 338
        IPC_SET_RETVAL(call->data, rc);
2886 svoboda 339
        ipc_answer(&TASK->kernel_box, call);
2815 svoboda 340
        return;
341
    }
342
 
343
    IPC_SET_RETVAL(call->data, 0);
2887 svoboda 344
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
2815 svoboda 345
       same code in process_answer() can be used
346
       (no way to distinguish method in answer) */
347
    IPC_SET_ARG1(call->data, uspace_dst);
348
    IPC_SET_ARG2(call->data, size);
349
    call->buffer = buffer;
350
 
351
    ipc_answer(&TASK->kernel_box, call);
352
}
353
 
2818 svoboda 354
static void udebug_receive_mem_write(call_t *call)
355
{
2887 svoboda 356
    unative_t uspace_dst;
2818 svoboda 357
    unsigned size;
358
    int rc;
359
 
360
    klog_printf("udebug_receive_mem_write()");
2827 svoboda 361
 
2887 svoboda 362
    uspace_dst = IPC_GET_ARG3(call->data);
2818 svoboda 363
    size = IPC_GET_ARG4(call->data);
364
 
2887 svoboda 365
    rc = udebug_mem_write(uspace_dst, call->buffer, size);
366
    if (rc < 0) {
2818 svoboda 367
        IPC_SET_RETVAL(call->data, rc);
2827 svoboda 368
        ipc_answer(&TASK->kernel_box, call);
2818 svoboda 369
        return;
370
    }
371
 
372
    IPC_SET_RETVAL(call->data, 0);
373
    free(call->buffer);
374
    call->buffer = NULL;
375
 
376
    ipc_answer(&TASK->kernel_box, call);
377
}
378
 
379
 
2815 svoboda 380
/**
381
 * Handle a debug call received on the kernel answerbox.
382
 *
383
 * This is called by the kbox servicing thread.
384
 */
385
void udebug_call_receive(call_t *call)
386
{
387
    int debug_method;
388
 
389
    debug_method = IPC_GET_ARG1(call->data);
390
 
2888 svoboda 391
    if (debug_method != UDEBUG_M_BEGIN) {
392
        /*
393
         * Verify that the sender is this task's debugger.
394
         * Note that this is the only thread that could change
395
         * TASK->debugger. Therefore no locking is necessary
396
         * and the sender can be safely considered valid until
397
         * control exits this function.
398
         */
399
        if (TASK->debugger != call->sender) {
400
            IPC_SET_RETVAL(call->data, EINVAL);
401
            ipc_answer(&TASK->kernel_box, call);
402
            return;
403
        }
404
    }
405
 
2815 svoboda 406
    switch (debug_method) {
2885 svoboda 407
    case UDEBUG_M_BEGIN:
408
        udebug_receive_begin(call);
409
        break;
410
    case UDEBUG_M_END:
411
        udebug_receive_end(call);
412
        break;
2886 svoboda 413
    case UDEBUG_M_GO:
414
        udebug_receive_go(call);
415
        break;
2885 svoboda 416
    case UDEBUG_M_THREAD_READ:
417
        udebug_receive_thread_read(call);
418
        break;
2886 svoboda 419
    case UDEBUG_M_ARGS_READ:
420
        udebug_receive_args_read(call);
421
        break;
422
    case UDEBUG_M_REGS_READ:
423
        udebug_receive_regs_read(call);
424
        break;
425
    case UDEBUG_M_REGS_WRITE:
426
        udebug_receive_regs_write(call);
427
        break;
2815 svoboda 428
    case UDEBUG_M_MEM_READ:
429
        udebug_receive_mem_read(call);
430
        break;
2818 svoboda 431
    case UDEBUG_M_MEM_WRITE:
432
        udebug_receive_mem_write(call);
433
        break;
2815 svoboda 434
    }
435
}
436
 
2813 svoboda 437
/** @}
438
 */