Subversion Repositories HelenOS

Rev

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