Statistics
| Branch: | Revision:

root / prex-0.9.0 / bsp / hal / arm / arch / context.c @ 03e9c04a

History | View | Annotate | Download (5.02 KB)

1
/*-
2
 * Copyright (c) 2005-2009, Kohsuke Ohtani
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
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. Neither the name of the author nor the names of any co-contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29

    
30
/*
31
 * context.c - context management routines
32
 */
33

    
34
/*
35
 * The context consists of kernel/user mode registers, and
36
 * kernel stack. The user mode registers are always saved to the
37
 * kernel stack when processor enters kernel mode by H/W or S/W events.
38
 *
39
 * The user mode registers are located in the interrupt/trap frame
40
 * at the top of the kernel stack. Before the control returns to user
41
 * mode next time, these register value will be restored automatically.
42
 *
43
 * All thread owns its context to keep its execution state. The
44
 * scheduler will switch the context to change an active thread.
45
 */
46

    
47
#include <kernel.h>
48
#include <kmem.h>
49
#include <cpu.h>
50
#include <context.h>
51
#include <locore.h>
52
#include <trap.h>
53

    
54
/*
55
 * Set data to the specific register stored in context.
56
 *
57
 * Note: When user mode program counter is set, all register
58
 * values except stack pointer are reset to default value.
59
 */
60
void
61
context_set(context_t ctx, int type, register_t val)
62
{
63
        struct kern_regs *k;
64
        struct cpu_regs *u;
65

    
66
        k = &ctx->kregs;
67

    
68
        switch (type) {
69
        case CTX_KSTACK:
70
                /* Set kernel mode stack pointer */
71
                ctx->uregs = (struct cpu_regs *)
72
                        ((vaddr_t)val - sizeof(struct cpu_regs));
73
                k->sp = (uint32_t)ctx->uregs;
74

    
75
                /* Reset minimum user mode registers */
76
                u = ctx->uregs;
77
                u->r0 = 0;
78
                u->r1 = 0x11111111;
79
                u->r2 = 0x22222222;
80
                u->r3 = 0x33333333;
81
                u->svc_sp = (uint32_t)val;
82
                u->cpsr = PSR_APP_MODE;        /* FIQ/IRQ is enabled */
83
                break;
84

    
85
        case CTX_KENTRY:
86
                /* Kernel mode program counter */
87
                k->lr = (uint32_t)&kernel_thread_entry;
88
                k->r4 = (uint32_t)val;
89
                break;
90

    
91
        case CTX_KARG:
92
                /* Kernel mode argument */
93
                k->r5 = (uint32_t)val;
94
                break;
95

    
96
        case CTX_USTACK:
97
                /* User mode stack pointer */
98
                u = ctx->uregs;
99
                u->sp = (uint32_t)val;
100
                break;
101

    
102
        case CTX_UENTRY:
103
                /* User mode program counter */
104
                u = ctx->uregs;
105
                u->cpsr = PSR_APP_MODE;        /* FIQ/IRQ is enabled */
106
                u->pc = (uint32_t)val;
107
                u->lr = 0x12345678;
108
                break;
109

    
110
        case CTX_UARG:
111
                /* User mode argument */
112
                u = ctx->uregs;
113
                u->r0 = (uint32_t)val;                /* Argument 1 */
114
                break;
115

    
116
        default:
117
                /* invalid */
118
                break;
119
        }
120
}
121

    
122
/*
123
 * Switch to new context
124
 *
125
 * Kernel mode registers and kernel stack pointer are switched to
126
 * the next context.
127
 *
128
 * It is assumed all interrupts are disabled by caller.
129
 *
130
 * TODO: FPU context is not switched as of now.
131
 */
132
void
133
context_switch(context_t prev, context_t next)
134
{
135

    
136
        cpu_switch(&prev->kregs, &next->kregs);
137
}
138

    
139
/*
140
 * Save user mode context to handle exceptions.
141
 *
142
 * Copy current user mode registers in the kernel stack to the user
143
 * mode stack. The user stack pointer is adjusted for this area.
144
 * So that the exception handler can get the register state of
145
 * the target thread.
146
 *
147
 * It builds arguments for the exception handler in the following
148
 * format.
149
 *
150
 *   void exception_handler(int exc, void *regs);
151
 */
152
void
153
context_save(context_t ctx)
154
{
155
        struct cpu_regs *cur, *sav;
156

    
157
        /* Copy current register context into user mode stack */
158
        cur = ctx->uregs;
159
        sav = (struct cpu_regs *)(cur->sp - sizeof(struct cpu_regs));
160
        copyout(cur, sav, sizeof(*sav));
161

    
162
        ctx->saved_regs = sav;
163

    
164
        /* Adjust stack pointer */
165
        cur->sp = (uint32_t)sav - sizeof(uint32_t);
166
}
167

    
168
/*
169
 * Restore register context to return from the exception handler.
170
 */
171
void
172
context_restore(context_t ctx)
173
{
174
        struct cpu_regs *cur;
175

    
176
        /* Restore user mode context */
177
        cur = ctx->uregs;
178
        copyin(ctx->saved_regs, cur, sizeof(*cur));
179

    
180
        /* Correct some registers for fail safe */
181
        cur->cpsr = (cur->cpsr & ~PSR_MODE) | PSR_APP_MODE;
182
}
183

    
184
void
185
context_dump(context_t ctx)
186
{
187

    
188
#ifdef DEBUG
189
        trap_dump(ctx->uregs);
190
#endif
191
}