Subversion Repositories HelenOS

Rev

Rev 2887 | Rev 2896 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2887 Rev 2894
-
 
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
 
1
/** @addtogroup generic
29
/** @addtogroup generic
2
 * @{
30
 * @{
3
 */
31
 */
4
 
32
 
5
/**
33
/**
6
 * @file
34
 * @file
7
 * @brief   Tdebug.
35
 * @brief   Udebug operations.
8
 */
36
 */
9
 
37
 
10
#include <console/klog.h>
38
#include <console/klog.h>
11
#include <proc/task.h>
39
#include <proc/task.h>
12
#include <proc/thread.h>
40
#include <proc/thread.h>
13
#include <arch.h>
41
#include <arch.h>
14
#include <errno.h>
42
#include <errno.h>
15
#include <syscall/copy.h>
43
#include <syscall/copy.h>
16
#include <ipc/ipc.h>
44
#include <ipc/ipc.h>
17
#include <udebug/udebug.h>
45
#include <udebug/udebug.h>
18
#include <udebug/udebug_ops.h>
46
#include <udebug/udebug_ops.h>
19
 
47
 
20
/**
48
/**
21
 * Prepare a thread for a debugging operation.
49
 * Prepare a thread for a debugging operation.
22
 *
50
 *
23
 * Simply put, return thread t with t->debug_lock held,
51
 * Simply put, return thread t with t->debug_lock held,
24
 * but only if it verifies all conditions.
52
 * but only if it verifies all conditions.
25
 *
53
 *
26
 * Specifically, verifies that thread t exists, is a userspace thread,
54
 * Specifically, verifies that thread t exists, is a userspace thread,
27
 * and belongs to the current task (TASK). It also locks t->debug_lock,
55
 * and belongs to the current task (TASK). It also locks t->debug_lock,
28
 * making sure that t->debug_active is true - that the thread is
56
 * making sure that t->debug_active is true - that the thread is
29
 * in a valid debugging session.
57
 * in a valid debugging session.
30
 *
58
 *
31
 * Returns EOK if all went well, or an error code otherwise.
59
 * Returns EOK if all went well, or an error code otherwise.
32
 * Interrupts must be already disabled when calling this function.
60
 * Interrupts must be already disabled when calling this function.
33
 *
61
 *
34
 * Note: This function sports complicated locking.
62
 * Note: This function sports complicated locking.
35
 */
63
 */
36
static int _thread_op_begin(thread_t *t)
64
static int _thread_op_begin(thread_t *t)
37
{
65
{
38
    int rc;
66
    int rc;
39
    task_id_t taskid;
67
    task_id_t taskid;
40
 
68
 
41
    taskid = TASK->taskid;
69
    taskid = TASK->taskid;
42
 
70
 
43
    /* Must lock threads_lock to ensure continued existence of the thread */
71
    /* Must lock threads_lock to ensure continued existence of the thread */
44
    spinlock_lock(&threads_lock);
72
    spinlock_lock(&threads_lock);
45
 
73
 
46
    if (!thread_exists(t)) {
74
    if (!thread_exists(t)) {
47
        spinlock_unlock(&threads_lock);
75
        spinlock_unlock(&threads_lock);
48
        return ENOENT;
76
        return ENOENT;
49
    }
77
    }
50
 
78
 
51
    spinlock_lock(&t->debug_lock);
79
    spinlock_lock(&t->debug_lock);
52
    spinlock_lock(&t->lock);
80
    spinlock_lock(&t->lock);
53
   
81
   
54
    /* Now verify that it's the current task */
82
    /* Now verify that it's the current task */
55
    if (t->task != TASK) {
83
    if (t->task != TASK) {
56
        /* No such thread belonging to callee */
84
        /* No such thread belonging to callee */
57
        rc = ENOENT;
85
        rc = ENOENT;
58
        goto error_exit;
86
        goto error_exit;
59
    }
87
    }
60
 
88
 
61
    /* Verify that 't' is a userspace thread */
89
    /* Verify that 't' is a userspace thread */
62
    if ((t->flags & THREAD_FLAG_USPACE) == 0) {
90
    if ((t->flags & THREAD_FLAG_USPACE) == 0) {
63
        /* It's not, deny its existence */
91
        /* It's not, deny its existence */
64
        rc = ENOENT;
92
        rc = ENOENT;
65
        goto error_exit;
93
        goto error_exit;
66
    }
94
    }
67
 
95
 
68
    if ((t->debug_active != true) || (t->debug_stop != true)) {
96
    if ((t->debug_active != true) || (t->debug_stop != true)) {
69
        /* Not in debugging session or already has GO */
97
        /* Not in debugging session or already has GO */
70
        rc = ENOENT;
98
        rc = ENOENT;
71
        goto error_exit;
99
        goto error_exit;
72
    }
100
    }
73
 
101
 
74
    spinlock_unlock(&threads_lock);
102
    spinlock_unlock(&threads_lock);
75
    spinlock_unlock(&t->lock);
103
    spinlock_unlock(&t->lock);
76
 
104
 
77
    /* Only t->debug_lock left */
105
    /* Only t->debug_lock left */
78
 
106
 
79
    return EOK; /* All went well */
107
    return EOK; /* All went well */
80
 
108
 
81
 
109
 
82
    /* Executed when a check on the thread fails */
110
    /* Executed when a check on the thread fails */
83
error_exit:
111
error_exit:
84
    spinlock_unlock(&t->lock);
112
    spinlock_unlock(&t->lock);
85
    spinlock_unlock(&t->debug_lock);
113
    spinlock_unlock(&t->debug_lock);
86
    spinlock_unlock(&threads_lock);
114
    spinlock_unlock(&threads_lock);
87
 
115
 
88
    /* No locks left here */
116
    /* No locks left here */
89
    return rc;  /* Some errors occured */
117
    return rc;  /* Some errors occured */
90
}
118
}
91
 
119
 
92
 
120
 
93
static void _thread_op_end(thread_t *t)
121
static void _thread_op_end(thread_t *t)
94
{
122
{
95
    spinlock_unlock(&t->debug_lock);
123
    spinlock_unlock(&t->debug_lock);
96
}
124
}
97
 
125
 
98
/**
126
/**
99
 * \return 0 (ok, but not done yet), 1 (done) or negative error code.
127
 * \return 0 (ok, but not done yet), 1 (done) or negative error code.
100
 */
128
 */
101
int udebug_begin(call_t *call)
129
int udebug_begin(call_t *call)
102
{
130
{
103
    ipl_t ipl;
131
    ipl_t ipl;
104
    int reply;
132
    int reply;
105
 
133
 
106
    thread_t *t;
134
    thread_t *t;
107
    link_t *cur;
135
    link_t *cur;
108
 
136
 
109
    klog_printf("udebug_begin()");
137
    klog_printf("udebug_begin()");
110
 
138
 
111
    ipl = interrupts_disable();
139
    ipl = interrupts_disable();
112
    klog_printf("debugging task %llu", TASK->taskid);
140
    klog_printf("debugging task %llu", TASK->taskid);
113
 
141
 
114
    spinlock_lock(&TASK->lock);
142
    spinlock_lock(&TASK->lock);
115
 
143
 
116
    if (TASK->dt_state != UDEBUG_TS_INACTIVE) {
144
    if (TASK->dt_state != UDEBUG_TS_INACTIVE) {
117
        spinlock_unlock(&TASK->lock);
145
        spinlock_unlock(&TASK->lock);
118
        interrupts_restore(ipl);
146
        interrupts_restore(ipl);
119
        klog_printf("udebug_begin(): busy error");
147
        klog_printf("udebug_begin(): busy error");
120
 
148
 
121
        return EBUSY;
149
        return EBUSY;
122
    }
150
    }
123
 
151
 
124
    TASK->dt_state = UDEBUG_TS_BEGINNING;
152
    TASK->dt_state = UDEBUG_TS_BEGINNING;
125
    TASK->debug_begin_call = call;
153
    TASK->debug_begin_call = call;
126
    TASK->debugger = call->sender;
154
    TASK->debugger = call->sender;
127
 
155
 
128
    if (TASK->not_stoppable_count == 0) {
156
    if (TASK->not_stoppable_count == 0) {
129
        TASK->dt_state = UDEBUG_TS_ACTIVE;
157
        TASK->dt_state = UDEBUG_TS_ACTIVE;
130
        TASK->debug_begin_call = NULL;
158
        TASK->debug_begin_call = NULL;
131
        reply = 1; /* immediate reply */
159
        reply = 1; /* immediate reply */
132
    } else {
160
    } else {
133
        reply = 0; /* no reply */
161
        reply = 0; /* no reply */
134
    }
162
    }
135
   
163
   
136
    /* Set debug_active on all of the task's userspace threads */
164
    /* Set debug_active on all of the task's userspace threads */
137
 
165
 
138
    for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
166
    for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
139
        t = list_get_instance(cur, thread_t, th_link);
167
        t = list_get_instance(cur, thread_t, th_link);
140
 
168
 
141
        spinlock_lock(&t->debug_lock);
169
        spinlock_lock(&t->debug_lock);
142
        if ((t->flags & THREAD_FLAG_USPACE) != 0)
170
        if ((t->flags & THREAD_FLAG_USPACE) != 0)
143
            t->debug_active = true;
171
            t->debug_active = true;
144
        spinlock_unlock(&t->debug_lock);
172
        spinlock_unlock(&t->debug_lock);
145
    }
173
    }
146
 
174
 
147
    spinlock_unlock(&TASK->lock);
175
    spinlock_unlock(&TASK->lock);
148
    interrupts_restore(ipl);
176
    interrupts_restore(ipl);
149
 
177
 
150
    klog_printf("udebug_begin() done (%s)",
178
    klog_printf("udebug_begin() done (%s)",
151
        reply ? "reply" : "stoppability wait");
179
        reply ? "reply" : "stoppability wait");
152
 
180
 
153
    return reply;
181
    return reply;
154
}
182
}
155
 
183
 
156
int udebug_end(void)
184
int udebug_end(void)
157
{
185
{
158
    ipl_t ipl;
186
    ipl_t ipl;
159
    int rc;
187
    int rc;
160
 
188
 
161
    klog_printf("udebug_end()");
189
    klog_printf("udebug_end()");
162
 
190
 
163
    ipl = interrupts_disable();
191
    ipl = interrupts_disable();
164
    spinlock_lock(&TASK->lock);
192
    spinlock_lock(&TASK->lock);
165
 
193
 
166
    rc = udebug_task_cleanup(TASK);
194
    rc = udebug_task_cleanup(TASK);
167
 
195
 
168
    klog_printf("task %llu", TASK->taskid);
196
    klog_printf("task %llu", TASK->taskid);
169
 
197
 
170
    spinlock_unlock(&TASK->lock);
198
    spinlock_unlock(&TASK->lock);
171
    interrupts_restore(ipl);
199
    interrupts_restore(ipl);
172
 
200
 
173
    if (rc < 0) return EINVAL;
201
    if (rc < 0) return EINVAL;
174
 
202
 
175
    return 0;
203
    return 0;
176
}
204
}
177
 
205
 
178
int udebug_go(thread_t *t, call_t *call)
206
int udebug_go(thread_t *t, call_t *call)
179
{
207
{
180
    ipl_t ipl;
208
    ipl_t ipl;
181
    int rc;
209
    int rc;
182
 
210
 
183
    klog_printf("udebug_go()");
211
    klog_printf("udebug_go()");
184
 
212
 
185
    ipl = interrupts_disable();
213
    ipl = interrupts_disable();
186
 
214
 
187
    /* On success, this will lock t->debug_lock */
215
    /* On success, this will lock t->debug_lock */
188
    rc = _thread_op_begin(t);
216
    rc = _thread_op_begin(t);
189
    if (rc != EOK) {
217
    if (rc != EOK) {
190
        interrupts_restore(ipl);
218
        interrupts_restore(ipl);
191
        return rc;
219
        return rc;
192
    }
220
    }
193
 
221
 
194
    t->debug_go_call = call;
222
    t->debug_go_call = call;
195
    t->debug_stop = false;
223
    t->debug_stop = false;
196
    t->cur_event = 0;   /* none */
224
    t->cur_event = 0;   /* none */
197
 
225
 
198
    /*
226
    /*
199
     * Neither t's lock nor threads_lock may be held during wakeup
227
     * Neither t's lock nor threads_lock may be held during wakeup
200
     */
228
     */
201
    waitq_wakeup(&t->go_wq, WAKEUP_FIRST);
229
    waitq_wakeup(&t->go_wq, WAKEUP_FIRST);
202
 
230
 
203
    _thread_op_end(t);
231
    _thread_op_end(t);
204
    interrupts_restore(ipl);
232
    interrupts_restore(ipl);
205
 
233
 
206
    return 0;
234
    return 0;
207
}
235
}
208
 
236
 
209
 
237
 
210
int udebug_thread_read(void **buffer, size_t *n)
238
int udebug_thread_read(void **buffer, size_t *n)
211
{
239
{
212
    thread_t *t;
240
    thread_t *t;
213
    link_t *cur;
241
    link_t *cur;
214
    unative_t tid;
242
    unative_t tid;
215
    unsigned num_threads, copied_ids;
243
    unsigned num_threads, copied_ids;
216
    ipl_t ipl;
244
    ipl_t ipl;
217
    unative_t *id_buffer;
245
    unative_t *id_buffer;
218
    int flags;
246
    int flags;
219
 
247
 
220
    klog_printf("udebug_thread_read()");
248
    klog_printf("udebug_thread_read()");
221
 
249
 
222
    ipl = interrupts_disable();
250
    ipl = interrupts_disable();
223
    spinlock_lock(&TASK->lock);
251
    spinlock_lock(&TASK->lock);
224
 
252
 
225
    /* Verify task state */
253
    /* Verify task state */
226
    if (TASK->dt_state != UDEBUG_TS_ACTIVE) {
254
    if (TASK->dt_state != UDEBUG_TS_ACTIVE) {
227
        spinlock_unlock(&TASK->lock);
255
        spinlock_unlock(&TASK->lock);
228
        interrupts_restore(ipl);
256
        interrupts_restore(ipl);
229
 
257
 
230
        return EINVAL;
258
        return EINVAL;
231
    }
259
    }
232
 
260
 
233
    /* Count the threads first */
261
    /* Count the threads first */
234
 
262
 
235
    num_threads = 0;
263
    num_threads = 0;
236
    for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
264
    for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
237
        /* Count all threads, to be on the safe side */
265
        /* Count all threads, to be on the safe side */
238
        ++num_threads;
266
        ++num_threads;
239
    }
267
    }
240
 
268
 
241
    /* Allocate a buffer and copy down the threads' ids */
269
    /* Allocate a buffer and copy down the threads' ids */
242
    id_buffer = malloc(num_threads * sizeof(unative_t), 0); // ???
270
    id_buffer = malloc(num_threads * sizeof(unative_t), 0); // ???
243
 
271
 
244
    copied_ids = 0;
272
    copied_ids = 0;
245
    for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
273
    for (cur = TASK->th_head.next; cur != &TASK->th_head; cur = cur->next) {
246
        t = list_get_instance(cur, thread_t, th_link);
274
        t = list_get_instance(cur, thread_t, th_link);
247
 
275
 
248
        spinlock_lock(&t->lock);
276
        spinlock_lock(&t->lock);
249
        flags = t->flags;
277
        flags = t->flags;
250
        spinlock_unlock(&t->lock);
278
        spinlock_unlock(&t->lock);
251
 
279
 
252
        /* Not interested in kernel threads */
280
        /* Not interested in kernel threads */
253
        if ((flags & THREAD_FLAG_USPACE) != 0) {
281
        if ((flags & THREAD_FLAG_USPACE) != 0) {
254
            /* Using thread struct pointer for identification */
282
            /* Using thread struct pointer for identification */
255
            tid = (unative_t) t;
283
            tid = (unative_t) t;
256
            id_buffer[copied_ids++] = tid;
284
            id_buffer[copied_ids++] = tid;
257
        }
285
        }
258
    }
286
    }
259
 
287
 
260
    spinlock_unlock(&TASK->lock);
288
    spinlock_unlock(&TASK->lock);
261
    interrupts_restore(ipl);
289
    interrupts_restore(ipl);
262
 
290
 
263
    *buffer = id_buffer;
291
    *buffer = id_buffer;
264
    *n = copied_ids * sizeof(unative_t);
292
    *n = copied_ids * sizeof(unative_t);
265
 
293
 
266
    return 0;
294
    return 0;
267
}
295
}
268
 
296
 
269
int udebug_args_read(thread_t *t, void **buffer)
297
int udebug_args_read(thread_t *t, void **buffer)
270
{
298
{
271
    int rc;
299
    int rc;
272
    ipl_t ipl;
300
    ipl_t ipl;
273
    unative_t *arg_buffer;
301
    unative_t *arg_buffer;
274
 
302
 
275
    klog_printf("udebug_args_read()");
303
    klog_printf("udebug_args_read()");
276
 
304
 
277
    ipl = interrupts_disable();
305
    ipl = interrupts_disable();
278
 
306
 
279
    /* On success, this will lock t->debug_lock */
307
    /* On success, this will lock t->debug_lock */
280
    rc = _thread_op_begin(t);
308
    rc = _thread_op_begin(t);
281
    if (rc != EOK) {
309
    if (rc != EOK) {
282
        interrupts_restore(ipl);
310
        interrupts_restore(ipl);
283
        return rc;
311
        return rc;
284
    }
312
    }
285
 
313
 
286
    /* Additionally we need to verify that we are inside a syscall */
314
    /* Additionally we need to verify that we are inside a syscall */
287
    if (t->cur_event != UDEBUG_EVENT_SYSCALL) {
315
    if (t->cur_event != UDEBUG_EVENT_SYSCALL) {
288
        _thread_op_end(t);
316
        _thread_op_end(t);
289
        interrupts_restore(ipl);
317
        interrupts_restore(ipl);
290
 
318
 
291
        return EINVAL;
319
        return EINVAL;
292
    }
320
    }
293
 
321
 
294
    /* Copy to a local buffer before releasing the lock */
322
    /* Copy to a local buffer before releasing the lock */
295
    arg_buffer = malloc(6 * sizeof(unative_t), 0); // ???
323
    arg_buffer = malloc(6 * sizeof(unative_t), 0); // ???
296
    memcpy(arg_buffer, t->syscall_args, 6 * sizeof(unative_t));
324
    memcpy(arg_buffer, t->syscall_args, 6 * sizeof(unative_t));
297
 
325
 
298
    _thread_op_end(t);
326
    _thread_op_end(t);
299
    interrupts_restore(ipl);
327
    interrupts_restore(ipl);
300
 
328
 
301
    *buffer = arg_buffer;
329
    *buffer = arg_buffer;
302
    return 0;
330
    return 0;
303
}
331
}
304
 
332
 
305
int udebug_regs_read(thread_t *t, void **buffer, size_t *n)
333
int udebug_regs_read(thread_t *t, void **buffer, size_t *n)
306
{
334
{
307
    istate_t *state;
335
    istate_t *state;
308
    void *regs_buffer;
336
    void *regs_buffer;
309
    int rc;
337
    int rc;
310
    ipl_t ipl;
338
    ipl_t ipl;
311
 
339
 
312
    klog_printf("udebug_regs_read()");
340
    klog_printf("udebug_regs_read()");
313
 
341
 
314
    ipl = interrupts_disable();
342
    ipl = interrupts_disable();
315
 
343
 
316
    /* On success, this will lock t->debug_lock */
344
    /* On success, this will lock t->debug_lock */
317
    rc = _thread_op_begin(t);
345
    rc = _thread_op_begin(t);
318
    if (rc != EOK) {
346
    if (rc != EOK) {
319
        interrupts_restore(ipl);
347
        interrupts_restore(ipl);
320
        return rc;
348
        return rc;
321
    }
349
    }
322
 
350
 
323
    state = t->uspace_state;
351
    state = t->uspace_state;
324
    if (state == NULL) {
352
    if (state == NULL) {
325
        _thread_op_end(t);
353
        _thread_op_end(t);
326
        interrupts_restore(ipl);
354
        interrupts_restore(ipl);
327
        klog_printf("udebug_regs_read() - istate not available");
355
        klog_printf("udebug_regs_read() - istate not available");
328
        return EBUSY;
356
        return EBUSY;
329
    }
357
    }
330
 
358
 
331
    /* Copy to an allocated buffer */
359
    /* Copy to an allocated buffer */
332
    regs_buffer = malloc(sizeof(istate_t), 0); // ???
360
    regs_buffer = malloc(sizeof(istate_t), 0); // ???
333
    memcpy(regs_buffer, state, sizeof(istate_t));
361
    memcpy(regs_buffer, state, sizeof(istate_t));
334
 
362
 
335
    _thread_op_end(t);
363
    _thread_op_end(t);
336
    interrupts_restore(ipl);
364
    interrupts_restore(ipl);
337
 
365
 
338
    *buffer = regs_buffer;
366
    *buffer = regs_buffer;
339
    *n = sizeof(istate_t);
367
    *n = sizeof(istate_t);
340
 
368
 
341
    return 0;
369
    return 0;
342
}
370
}
343
 
371
 
344
int udebug_regs_write(thread_t *t, void *buffer)
372
int udebug_regs_write(thread_t *t, void *buffer)
345
{
373
{
346
    int rc;
374
    int rc;
347
    istate_t *state;
375
    istate_t *state;
348
    ipl_t ipl;
376
    ipl_t ipl;
349
 
377
 
350
    klog_printf("udebug_regs_write()");
378
    klog_printf("udebug_regs_write()");
351
 
379
 
352
    /* Try to change the thread's uspace_state */
380
    /* Try to change the thread's uspace_state */
353
 
381
 
354
    ipl = interrupts_disable();
382
    ipl = interrupts_disable();
355
 
383
 
356
    /* On success, this will lock t->debug_lock */
384
    /* On success, this will lock t->debug_lock */
357
    rc = _thread_op_begin(t);
385
    rc = _thread_op_begin(t);
358
    if (rc != EOK) {
386
    if (rc != EOK) {
359
        interrupts_restore(ipl);
387
        interrupts_restore(ipl);
360
        return rc;
388
        return rc;
361
    }
389
    }
362
 
390
 
363
    state = t->uspace_state;
391
    state = t->uspace_state;
364
    if (state == NULL) {
392
    if (state == NULL) {
365
        _thread_op_end(t);
393
        _thread_op_end(t);
366
        interrupts_restore(ipl);
394
        interrupts_restore(ipl);
367
        klog_printf("udebug_regs_write() - istate not available");
395
        klog_printf("udebug_regs_write() - istate not available");
368
 
396
 
369
        return EBUSY;
397
        return EBUSY;
370
    }
398
    }
371
 
399
 
372
    memcpy(t->uspace_state, buffer, sizeof(t->uspace_state));
400
    memcpy(t->uspace_state, buffer, sizeof(t->uspace_state));
373
 
401
 
374
    _thread_op_end(t);
402
    _thread_op_end(t);
375
    interrupts_restore(ipl);
403
    interrupts_restore(ipl);
376
 
404
 
377
    return 0;
405
    return 0;
378
}
406
}
379
 
407
 
380
 
408
 
381
int udebug_mem_read(unative_t uspace_addr, size_t n, void **buffer)
409
int udebug_mem_read(unative_t uspace_addr, size_t n, void **buffer)
382
{
410
{
383
    void *data_buffer;
411
    void *data_buffer;
384
    int rc;
412
    int rc;
385
 
413
 
386
    klog_printf("udebug_mem_read()");
414
    klog_printf("udebug_mem_read()");
387
 
415
 
388
    data_buffer = malloc(n, 0); // ???
416
    data_buffer = malloc(n, 0); // ???
389
    klog_printf("udebug_mem_read: src=%u, size=%u", uspace_addr, n);
417
    klog_printf("udebug_mem_read: src=%u, size=%u", uspace_addr, n);
390
 
418
 
391
    /* NOTE: this is not strictly from a syscall... but that shouldn't
419
    /* NOTE: this is not strictly from a syscall... but that shouldn't
392
     * be a problem */
420
     * be a problem */
393
    rc = copy_from_uspace(data_buffer, (void *)uspace_addr, n);
421
    rc = copy_from_uspace(data_buffer, (void *)uspace_addr, n);
394
    if (rc) return rc;
422
    if (rc) return rc;
395
 
423
 
396
    *buffer = data_buffer;
424
    *buffer = data_buffer;
397
    return 0;
425
    return 0;
398
}
426
}
399
 
427
 
400
int udebug_mem_write(unative_t uspace_addr, void *data, size_t n)
428
int udebug_mem_write(unative_t uspace_addr, void *data, size_t n)
401
{
429
{
402
    int rc;
430
    int rc;
403
    udebug_task_state_t dts;
431
    udebug_task_state_t dts;
404
 
432
 
405
    klog_printf("udebug_mem_write()");
433
    klog_printf("udebug_mem_write()");
406
 
434
 
407
    /* Verify task state */
435
    /* Verify task state */
408
    spinlock_lock(&TASK->lock);
436
    spinlock_lock(&TASK->lock);
409
    dts = TASK->dt_state;
437
    dts = TASK->dt_state;
410
    spinlock_unlock(&TASK->lock);
438
    spinlock_unlock(&TASK->lock);
411
 
439
 
412
    if (dts != UDEBUG_TS_ACTIVE)
440
    if (dts != UDEBUG_TS_ACTIVE)
413
        return EBUSY;
441
        return EBUSY;
414
   
442
   
415
    klog_printf("dst=%u, size=%u", uspace_addr, n);
443
    klog_printf("dst=%u, size=%u", uspace_addr, n);
416
 
444
 
417
    /* NOTE: this is not strictly from a syscall... but that shouldn't
445
    /* NOTE: this is not strictly from a syscall... but that shouldn't
418
     * be a problem */
446
     * be a problem */
419
    rc = copy_to_uspace((void *)uspace_addr, data, n);
447
    rc = copy_to_uspace((void *)uspace_addr, data, n);
420
    if (rc) return rc;
448
    if (rc) return rc;
421
 
449
 
422
    return 0;
450
    return 0;
423
}
451
}
424
 
452
 
425
/** @}
453
/** @}
426
 */
454
 */
427
 
455