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

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

Document functions in udebug.c and udebug_ops.c

  • Property mode set to 100644
File size: 6.9 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 * This module handles udebug IPC messages and calls the appropriate
38 * functions from the udebug_ops module which implement them.
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
51int 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
62static 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
79static 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
89static 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
102static 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
117static 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
129static 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
179static 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
212static 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 */
247void 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 */
Note: See TracBrowser for help on using the repository browser.