Project

General

Profile

Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (5.08 KB)

1 03e9c04a Brad Neuman
/*-
2
 * Copyright (c) 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 kernel
36
 * stack. The user mode registers are always saved to the kernel
37
 * 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
40
 * frame at the top of the kernel stack. Before the control
41
 * returns to user mode next time, these register value will be
42
 * restored automatically.
43
 *
44
 * All thread owns its context to keep its execution state. The
45
 * scheduler will switch the context to change an active thread.
46
 */
47
48
#include <kernel.h>
49
#include <kmem.h>
50
#include <cpu.h>
51
#include <context.h>
52
#include <locore.h>
53
#include <trap.h>
54
55
/*
56
 * Set user mode registers into the specific context.
57
 *
58
 * Note: When user mode program counter is set, all register
59
 * values except a stack pointer are reset to default value.
60
 */
61
void
62
context_set(context_t ctx, int type, register_t val)
63
{
64
        struct kern_regs *k;
65
        struct cpu_regs *u;
66
        uint32_t *argp;
67
68
        k = &ctx->kregs;
69
70
        switch (type) {
71
        case CTX_KSTACK:
72
                /* Adjust stack for C code */
73
                val -= STKFRAME_LEN;
74
75
                /* Set kernel mode stack pointer */
76
                ctx->uregs = (struct cpu_regs *)
77
                                ((uint32_t)val - sizeof(struct cpu_regs));
78
79
                k->sp = (uint32_t)ctx->uregs;
80
                k->kstack = (uint32_t)val;
81
82
                /* Reset minimum user mode registers */
83
                u = ctx->uregs;
84
                u->gr[3] = 0x11111111;
85
                u->gr[4] = 0x22222222;
86
                u->gr[5] = 0x33333333;
87
                u->srr1 = MSR_DFLT;
88
                break;
89
90
        case CTX_KENTRY:
91
                /* Kernel mode program counter */
92
                k->lr = (uint32_t)val;
93
                break;
94
95
        case CTX_KARG:
96
                /* Kernel mode argument */
97
                argp = (uint32_t *)(k->sp + sizeof(uint32_t) * 2);
98
                *argp = (uint32_t)val;
99
                break;
100
101
        case CTX_USTACK:
102
                /* User mode stack pointer */
103
                u = ctx->uregs;
104
                u->gr[1] = (uint32_t)val;
105
                break;
106
107
        case CTX_UENTRY:
108
                /* User mode program counter */
109
                u = ctx->uregs;
110
                u->srr0 = (uint32_t)val;
111
                u->srr1 = MSR_DFLT;
112
                break;
113
114
        case CTX_UARG:
115
                /* User mode argument */
116
                u = ctx->uregs;
117
                u->gr[3] = (uint32_t)val;
118
                argp = (uint32_t *)(u->gr[1] + sizeof(uint32_t));
119
                copyout(&val, argp, sizeof(uint32_t));
120
                break;
121
122
        default:
123
                /* invalid */
124
                break;
125
        }
126
}
127
128
/*
129
 * Switch to new context
130
 *
131
 * Kernel mode registers and kernel stack pointer are switched to
132
 * the next context.
133
 *
134
 * It is assumed all interrupts are disabled by caller.
135
 *
136
 * TODO: FPU context is not switched as of now.
137
 */
138
void
139
context_switch(context_t prev, context_t next)
140
{
141
142
        cpu_switch(&prev->kregs, &next->kregs);
143
}
144
145
/*
146
 * Save user mode context to handle exceptions.
147
 *
148
 * Copy current user mode registers in the kernel stack to the
149
 * user mode stack. The user stack pointer is adjusted for this
150
 * area. So that the exception handler can get the register
151
 * state of the target thread.
152
 *
153
 * It builds arguments for the exception handler in the following
154
 * format.
155
 *
156
 *   void exception_handler(int exc, void *regs);
157
 */
158
void
159
context_save(context_t ctx)
160
{
161
        struct cpu_regs *cur, *sav;
162
163
        /* Copy current register context into user mode stack */
164
        cur = ctx->uregs;
165
        sav = (struct cpu_regs *)(cur->gr[1] - sizeof(struct cpu_regs));
166
        copyout(cur, sav, sizeof(*sav));
167
168
        ctx->saved_regs = sav;
169
170
        /* Adjust stack pointer */
171
        cur->gr[1] = (uint32_t)sav - sizeof(uint32_t);
172
}
173
174
/*
175
 * Restore register context to return from the exception handler.
176
 */
177
void
178
context_restore(context_t ctx)
179
{
180
        struct cpu_regs *cur;
181
182
        /* Restore user mode context */
183
        cur = ctx->uregs;
184
        copyin(ctx->saved_regs, cur, sizeof(*cur));
185
186
        /* Correct some registers for fail safe */
187
        cur->srr1 |= MSR_DFLT;
188
}
189
190
void
191
context_dump(context_t ctx)
192
{
193
194
#ifdef DEBUG
195
        trap_dump(ctx->uregs);
196
#endif
197
}