OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [src/] [api/] [exregs.c] - Blame information for rev 7

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 drasko
#include <l4/lib/mutex.h>
2
#include <l4/lib/printk.h>
3
#include <l4/generic/scheduler.h>
4
#include <l4/generic/tcb.h>
5
#include <l4/generic/resource.h>
6
#include <l4/generic/tcb.h>
7
#include <l4/generic/space.h>
8
#include <l4/generic/capability.h>
9
#include <l4/generic/container.h>
10
#include <l4/api/ipc.h>
11
#include <l4/api/kip.h>
12
#include <l4/api/errno.h>
13
#include <l4/api/exregs.h>
14
 
15
/* Copy each register to task's context if its valid bit is set */
16
void exregs_write_registers(struct ktcb *task, struct exregs_data *exregs)
17
{
18
        task_context_t *context = &task->context;
19
 
20
        if (!exregs->valid_vect)
21
                goto flags;
22
        /*
23
         * NOTE:
24
         * We don't care if register values point at invalid addresses
25
         * since memory protection would prevent any kernel corruption.
26
         * We do however, make sure spsr is not modified
27
         */
28
 
29
        /* Check register valid bit and copy registers */
30
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r0))
31
                context->r0 = exregs->context.r0;
32
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r1))
33
                context->r1 = exregs->context.r1;
34
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r2))
35
                context->r2 = exregs->context.r2;
36
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r3))
37
                context->r3 = exregs->context.r3;
38
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r4))
39
                context->r4 = exregs->context.r4;
40
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r5))
41
                context->r5 = exregs->context.r5;
42
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r6))
43
                context->r6 = exregs->context.r6;
44
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r7))
45
                context->r7 = exregs->context.r7;
46
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r8))
47
                context->r8 = exregs->context.r8;
48
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r9))
49
                context->r9 = exregs->context.r9;
50
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r10))
51
                context->r10 = exregs->context.r10;
52
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r11))
53
                context->r11 = exregs->context.r11;
54
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r12))
55
                context->r12 = exregs->context.r12;
56
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, sp))
57
                context->sp = exregs->context.sp;
58
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, lr))
59
                context->lr = exregs->context.lr;
60
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, pc))
61
                context->pc = exregs->context.pc;
62
 
63
flags:
64
        /* Set thread's pager if one is supplied */
65
        if (exregs->flags & EXREGS_SET_PAGER)
66
                task->pagerid = exregs->pagerid;
67
 
68
        /* Set thread's utcb if supplied */
69
        if (exregs->flags & EXREGS_SET_UTCB) {
70
                task->utcb_address = exregs->utcb_address;
71
 
72
                /*
73
                 * If task is the one currently runnable,
74
                 * update utcb reference
75
                 */
76
                if (task == current)
77
                        task_update_utcb(task);
78
        }
79
}
80
 
81
void exregs_read_registers(struct ktcb *task, struct exregs_data *exregs)
82
{
83
        task_context_t *context = &task->context;
84
 
85
        if (!exregs->valid_vect)
86
                goto flags;
87
 
88
        /* Check register valid bit and copy registers */
89
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r0))
90
                exregs->context.r0 = context->r0;
91
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r1))
92
                exregs->context.r1 = context->r1;
93
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r2))
94
                exregs->context.r2 = context->r2;
95
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r3))
96
                exregs->context.r3 = context->r3;
97
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r4))
98
                exregs->context.r4 = context->r4;
99
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r5))
100
                exregs->context.r5 = context->r5;
101
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r6))
102
                exregs->context.r6 = context->r6;
103
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r7))
104
                exregs->context.r7 = context->r7;
105
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r8))
106
                exregs->context.r8 = context->r8;
107
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r9))
108
                exregs->context.r9 = context->r9;
109
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r10))
110
                exregs->context.r10 = context->r10;
111
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r11))
112
                exregs->context.r11 = context->r11;
113
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, r12))
114
                exregs->context.r12 = context->r12;
115
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, sp))
116
                exregs->context.sp = context->sp;
117
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, lr))
118
                exregs->context.lr = context->lr;
119
        if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, pc))
120
                exregs->context.pc = context->pc;
121
 
122
flags:
123
        /* Read thread's pager if pager flag supplied */
124
        if (exregs->flags & EXREGS_SET_PAGER)
125
                exregs->pagerid = task->pagerid;
126
 
127
        /* Read thread's utcb if utcb flag supplied */
128
        if (exregs->flags & EXREGS_SET_UTCB)
129
                exregs->utcb_address = task->utcb_address;
130
}
131
 
132
/*
133
 * exchange_registers()
134
 *
135
 * This call is used by the pagers to set (and in the future read)
136
 * the register context of a thread. The thread's registers that are
137
 * set by this call are loaded whenever the thread gets a chance to
138
 * run in user mode.
139
 *
140
 * It is ensured that whenever this call is made, the thread is
141
 * either already running in user mode, or has been suspended in
142
 * kernel mode, just before returning to user mode.
143
 *
144
 * A newly created thread that is the copy of another thread (forked
145
 * or cloned) will also be given its user mode context on the first
146
 * chance to execute so such threads can also be modified by this
147
 * call before execution.
148
 *
149
 * A thread executing in the kernel cannot be modified since this
150
 * would compromise the kernel. Also the thread must be in suspended
151
 * condition so that the scheduler does not execute it as we modify
152
 * its context.
153
 *
154
 * FIXME: Still looks like suspended threads in the kernel
155
 * need to be made immutable. see src/glue/arm/systable.c
156
 */
157
int sys_exchange_registers(struct exregs_data *exregs, l4id_t tid)
158
{
159
        int err = 0;
160
        struct ktcb *task;
161
 
162
        if ((err = check_access((unsigned long)exregs,
163
                                sizeof(*exregs),
164
                                MAP_USR_RW, 1)) < 0)
165
                return err;
166
 
167
        /* Find tcb from its list */
168
        if (!(task = tcb_find(tid)))
169
                return -ESRCH;
170
 
171
        /*
172
         * This lock ensures task is not
173
         * inadvertently resumed by a syscall
174
         */
175
        if (!mutex_trylock(&task->thread_control_lock))
176
                return -EAGAIN;
177
 
178
        /*
179
         * Now check that the task is suspended.
180
         *
181
         * Only modification of non-register fields are
182
         * allowed on active tasks and those tasks must
183
         * be the pagers making the call on themselves.
184
         */
185
        if (task->state != TASK_INACTIVE && exregs->valid_vect &&
186
            current != task && task->pagerid != current->tid) {
187
                err = -EACTIVE;
188
                goto out;
189
        }
190
 
191
        if ((err = cap_exregs_check(task, exregs)) < 0)
192
                return -ENOCAP;
193
 
194
        /* Copy registers */
195
        if (exregs->flags & EXREGS_READ)
196
                exregs_read_registers(task, exregs);
197
        else
198
                exregs_write_registers(task, exregs);
199
 
200
out:
201
        /* Unlock and return */
202
        mutex_unlock(&task->thread_control_lock);
203
        return err;
204
}
205
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.