source: mainline/kernel/generic/src/udebug/udebug_ipc.c@ d1c8287

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d1c8287 was 0108984a, checked in by Jiri Svoboda <jirik.svoboda@…>, 17 years ago

Use LOG() instead of printf() for debug messages.

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