Subversion Repositories HelenOS

Rev

Rev 3441 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3438 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
 
29
/** @addtogroup generic
30
 * @{
31
 */
32
 
33
/**
34
 * @file
35
 * @brief   Udebug IPC message handling.
36
 */
37
 
38
#include <print.h>
39
#include <proc/task.h>
40
#include <proc/thread.h>
41
#include <arch.h>
42
#include <errno.h>
43
#include <ipc/ipc.h>
44
#include <syscall/copy.h>
45
#include <udebug/udebug.h>
46
#include <udebug/udebug_ops.h>
47
#include <udebug/udebug_ipc.h>
48
 
49
int udebug_request_preprocess(call_t *call, phone_t *phone)
50
{
51
    switch (IPC_GET_ARG1(call->data)) {
52
    /* future UDEBUG_M_REGS_WRITE, UDEBUG_M_MEM_WRITE: */
53
    default:
54
        break;
55
    }
56
 
57
    return 0;
58
}
59
 
60
static void udebug_receive_begin(call_t *call)
61
{
62
    int rc;
63
 
64
    rc = udebug_begin(call);
65
    if (rc < 0) {
66
        IPC_SET_RETVAL(call->data, rc);
67
        ipc_answer(&TASK->kernel_box, call);
68
        return;
69
    }
70
 
71
    if (rc != 0) {
72
        IPC_SET_RETVAL(call->data, 0);
73
        ipc_answer(&TASK->kernel_box, call);
74
    }
75
}
76
 
77
static void udebug_receive_end(call_t *call)
78
{
79
    int rc;
80
 
81
    rc = udebug_end();
82
 
83
    IPC_SET_RETVAL(call->data, rc);
84
    ipc_answer(&TASK->kernel_box, call);
85
}
86
 
87
static void udebug_receive_set_evmask(call_t *call)
88
{
89
    int rc;
90
    udebug_evmask_t mask;
91
 
92
    mask = IPC_GET_ARG2(call->data);
93
    rc = udebug_set_evmask(mask);
94
 
95
    IPC_SET_RETVAL(call->data, rc);
96
    ipc_answer(&TASK->kernel_box, call);
97
}
98
 
99
 
100
static void udebug_receive_go(call_t *call)
101
{
102
    thread_t *t;
103
    int rc;
104
 
105
    //printf("debug_go()\n");
106
 
107
    t = (thread_t *)IPC_GET_ARG2(call->data);
108
 
109
    rc = udebug_go(t, call);
110
    if (rc < 0) {
111
        IPC_SET_RETVAL(call->data, rc);
112
        ipc_answer(&TASK->kernel_box, call);
113
        return;
114
    }
115
}
116
 
117
static void udebug_receive_stop(call_t *call)
118
{
119
    thread_t *t;
120
    int rc;
121
 
122
    printf("debug_stop()\n");
123
 
124
    t = (thread_t *)IPC_GET_ARG2(call->data);
125
 
126
    rc = udebug_stop(t, call);
127
    IPC_SET_RETVAL(call->data, rc);
128
    ipc_answer(&TASK->kernel_box, call);
129
}
130
 
131
static void udebug_receive_thread_read(call_t *call)
132
{
133
    unative_t uspace_addr;
134
    unative_t to_copy;
135
    unsigned total_bytes;
136
    unsigned buf_size;
137
    void *buffer;
138
    size_t n;
139
    int rc;
140
 
141
    uspace_addr = IPC_GET_ARG2(call->data); /* Destination address */
142
    buf_size = IPC_GET_ARG3(call->data);    /* Dest. buffer size */
143
 
144
    /*
145
     * Read thread list. Variable n will be filled with actual number
146
     * of threads times thread-id size.
147
     */
148
    rc = udebug_thread_read(&buffer, buf_size, &n);
149
    if (rc < 0) {
150
        IPC_SET_RETVAL(call->data, rc);
151
        ipc_answer(&TASK->kernel_box, call);
152
        return;
153
    }
154
 
155
    total_bytes = n;
156
 
157
    /* Copy MAX(buf_size, total_bytes) bytes */
158
 
159
    if (buf_size > total_bytes)
160
        to_copy = total_bytes;
161
    else
162
        to_copy = buf_size;
163
 
164
    /*
165
     * Make use of call->buffer to transfer data to caller's userspace
166
     */
167
 
168
    IPC_SET_RETVAL(call->data, 0);
169
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
170
       same code in process_answer() can be used
171
       (no way to distinguish method in answer) */
172
    IPC_SET_ARG1(call->data, uspace_addr);
173
    IPC_SET_ARG2(call->data, to_copy);
174
 
175
    IPC_SET_ARG3(call->data, total_bytes);
176
    call->buffer = buffer;
177
 
178
    ipc_answer(&TASK->kernel_box, call);
179
}
180
 
181
static void udebug_receive_args_read(call_t *call)
182
{
183
    thread_t *t;
184
    unative_t uspace_addr;
185
    int rc;
186
    void *buffer;
187
 
188
    t = (thread_t *)IPC_GET_ARG2(call->data);
189
 
190
    rc = udebug_args_read(t, &buffer);
191
    if (rc != EOK) {
192
        IPC_SET_RETVAL(call->data, rc);
193
        ipc_answer(&TASK->kernel_box, call);
194
        return;
195
    }
196
 
197
    /*
198
     * Make use of call->buffer to transfer data to caller's userspace
199
     */
200
 
201
    uspace_addr = IPC_GET_ARG3(call->data);
202
 
203
    IPC_SET_RETVAL(call->data, 0);
204
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
205
       same code in process_answer() can be used
206
       (no way to distinguish method in answer) */
207
    IPC_SET_ARG1(call->data, uspace_addr);
208
    IPC_SET_ARG2(call->data, 6 * sizeof(unative_t));
209
    call->buffer = buffer;
210
 
211
    ipc_answer(&TASK->kernel_box, call);
212
}
213
 
214
static void udebug_receive_mem_read(call_t *call)
215
{
216
    unative_t uspace_dst;
217
    unative_t uspace_src;
218
    unsigned size;
219
    void *buffer;
220
    int rc;
221
 
222
    uspace_dst = IPC_GET_ARG2(call->data);
223
    uspace_src = IPC_GET_ARG3(call->data);
224
    size = IPC_GET_ARG4(call->data);
225
 
226
    rc = udebug_mem_read(uspace_src, size, &buffer);
227
    if (rc < 0) {
228
        IPC_SET_RETVAL(call->data, rc);
229
        ipc_answer(&TASK->kernel_box, call);
230
        return;
231
    }
232
 
233
    IPC_SET_RETVAL(call->data, 0);
234
    /* ARG1=dest, ARG2=size as in IPC_M_DATA_READ so that
235
       same code in process_answer() can be used
236
       (no way to distinguish method in answer) */
237
    IPC_SET_ARG1(call->data, uspace_dst);
238
    IPC_SET_ARG2(call->data, size);
239
    call->buffer = buffer;
240
 
241
    ipc_answer(&TASK->kernel_box, call);
242
}
243
 
244
/**
245
 * Handle a debug call received on the kernel answerbox.
246
 *
247
 * This is called by the kbox servicing thread.
248
 */
249
void udebug_call_receive(call_t *call)
250
{
251
    int debug_method;
252
 
253
    debug_method = IPC_GET_ARG1(call->data);
254
 
255
    if (debug_method != UDEBUG_M_BEGIN) {
256
        /*
257
         * Verify that the sender is this task's debugger.
258
         * Note that this is the only thread that could change
259
         * TASK->debugger. Therefore no locking is necessary
260
         * and the sender can be safely considered valid until
261
         * control exits this function.
262
         */
263
        if (TASK->udebug.debugger != call->sender) {
264
            IPC_SET_RETVAL(call->data, EINVAL);
265
            ipc_answer(&TASK->kernel_box, call);
266
            return;
267
        }
268
    }
269
 
270
    switch (debug_method) {
271
    case UDEBUG_M_BEGIN:
272
        udebug_receive_begin(call);
273
        break;
274
    case UDEBUG_M_END:
275
        udebug_receive_end(call);
276
        break;
277
    case UDEBUG_M_SET_EVMASK:
278
        udebug_receive_set_evmask(call);
279
        break;
280
    case UDEBUG_M_GO:
281
        udebug_receive_go(call);
282
        break;
283
    case UDEBUG_M_STOP:
284
        udebug_receive_stop(call);
285
        break;
286
    case UDEBUG_M_THREAD_READ:
287
        udebug_receive_thread_read(call);
288
        break;
289
    case UDEBUG_M_ARGS_READ:
290
        udebug_receive_args_read(call);
291
        break;
292
    case UDEBUG_M_MEM_READ:
293
        udebug_receive_mem_read(call);
294
        break;
295
    }
296
}
297
 
298
/** @}
299
 */