|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/bsp/hal/x86/arch/context.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.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 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 <trap.h> 52 #include <context.h> 53 #include <locore.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 /* Set kernel mode stack pointer */ 73 ctx->uregs = (struct cpu_regs *) 74 ((uint32_t)val - sizeof(struct cpu_regs)); 75 ctx->esp0 = (uint32_t)val; 76 77 k->eip = (uint32_t)&syscall_ret; 78 k->esp = (uint32_t)ctx->uregs - sizeof(uint32_t); 79 80 /* Reset minimum user mode registers */ 81 u = ctx->uregs; 82 u->eax = 0; 83 u->eflags = (uint32_t)(EFL_IF | EFL_IOPL_KERN); 84 break; 85 86 case CTX_KENTRY: 87 /* Kernel mode program counter */ 88 k->eip = (uint32_t)val; 89 break; 90 91 case CTX_KARG: 92 /* Kernel mode argument */ 93 argp = (uint32_t *)(k->esp + sizeof(uint32_t) * 2); 94 *argp = (uint32_t)val; 95 break; 96 97 case CTX_USTACK: 98 /* User mode stack pointer */ 99 u = ctx->uregs; 100 u->esp = (uint32_t)val; 101 u->ss = (uint32_t)(USER_DS | 3); /* fail safe */ 102 break; 103 104 case CTX_UENTRY: 105 /* User mode program counter */ 106 u = ctx->uregs; 107 u->eip = (uint32_t)val; 108 u->cs = (uint32_t)(USER_CS | 3); 109 u->ds = u->es = (uint32_t)(USER_DS | 3); 110 u->eflags = (uint32_t)(EFL_IF | EFL_IOPL_KERN); 111 u->eax = u->ebx = u->ecx = u->edx = 112 u->edi = u->esi = u->ebp = 0; 113 break; 114 115 case CTX_UARG: 116 /* User mode argument */ 117 u = ctx->uregs; 118 argp = (uint32_t *)(u->esp + 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 * We don't use x86 task switch mechanism to minimize the context 135 * space. The system has only one TSS(task state segment), and 136 * the context switching is done by changing the register value 137 * in this TSS. Processor will reload them automatically when it 138 * enters to the kernel mode in next time. 139 * 140 * It is assumed all interrupts are disabled by caller. 141 * 142 * TODO: FPU context is not switched as of now. 143 */ 144 void 145 context_switch(context_t prev, context_t next) 146 { 147 /* Set kernel stack pointer in TSS (esp0). */ 148 tss_set((uint32_t)next->esp0); 149 150 /* Save the previous context, and restore the next context */ 151 cpu_switch(&prev->kregs, &next->kregs); 152 } 153 154 /* 155 * Save user mode context to handle exceptions. 156 * 157 * Copy current user mode registers in the kernel stack to the 158 * user mode stack. The user stack pointer is adjusted for this 159 * area. So that the exception handler can get the register 160 * state of the target thread. 161 * 162 * It builds arguments for the exception handler in the following 163 * format. 164 * 165 * void exception_handler(int exc, void *regs); 166 */ 167 void 168 context_save(context_t ctx) 169 { 170 struct cpu_regs *cur, *sav; 171 172 /* Copy current register context into user mode stack */ 173 cur = ctx->uregs; 174 sav = (struct cpu_regs *)(cur->esp - sizeof(*sav)); 175 copyout(cur, sav, sizeof(*sav)); 176 177 178 ctx->saved_regs = sav; 179 180 /* Adjust stack pointer */ 181 cur->esp = (uint32_t)sav - (sizeof(uint32_t) * 2); 182 } 183 184 /* 185 * Restore register context to return from the exception handler. 186 */ 187 void 188 context_restore(context_t ctx) 189 { 190 struct cpu_regs *cur; 191 192 /* Restore user mode context */ 193 cur = ctx->uregs; 194 copyin(ctx->saved_regs, cur, sizeof(*cur)); 195 196 /* Correct some registers for fail safe */ 197 cur->cs = (uint32_t)(USER_CS | 3); 198 cur->ss = cur->ds = cur->es = (uint32_t)(USER_DS | 3); 199 cur->eflags |= EFL_IF; 200 } 201 202 void 203 context_dump(context_t ctx) 204 { 205 206 #ifdef DEBUG 207 trap_dump(ctx->uregs); 208 #endif 209 } /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |