Annotation of prex-old/sys/arch/i386/i386/context.c, Revision 1.1.1.1.2.1
1.1 nbrk 1: /*-
2: * Copyright (c) 2005, 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: /*
1.1.1.1.2.1! nbrk 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.
1.1 nbrk 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 <cpu.h>
50: #include <locore.h>
51:
52: /*
1.1.1.1.2.1! nbrk 53: * Set user mode registers into the specific context.
1.1 nbrk 54: *
1.1.1.1.2.1! nbrk 55: * Note: When user mode program counter is set, all register
! 56: * values except a stack pointer are reset to default value.
1.1 nbrk 57: */
58: void
1.1.1.1.2.1! nbrk 59: context_set(context_t ctx, int type, vaddr_t val)
1.1 nbrk 60: {
61: struct kern_regs *k;
62: struct cpu_regs *u;
1.1.1.1.2.1! nbrk 63: uint32_t *argp;
1.1 nbrk 64:
65: k = &ctx->kregs;
66:
1.1.1.1.2.1! nbrk 67: switch (type) {
! 68: case CTX_KSTACK:
! 69: /* Set kernel mode stack pointer */
! 70: ctx->uregs = (struct cpu_regs *)
! 71: ((uint32_t)val - sizeof(struct cpu_regs));
! 72: ctx->esp0 = (uint32_t)val;
1.1 nbrk 73:
1.1.1.1.2.1! nbrk 74: k->eip = (uint32_t)&syscall_ret;
! 75: k->esp = (uint32_t)ctx->uregs - sizeof(uint32_t);
1.1 nbrk 76:
1.1.1.1.2.1! nbrk 77: /* Reset minimum user mode registers */
! 78: u = ctx->uregs;
! 79: u->eax = 0;
! 80: u->eflags = (uint32_t)(EFL_IF | EFL_IOPL_KERN);
! 81: break;
! 82:
! 83: case CTX_KENTRY:
! 84: /* Kernel mode program counter */
! 85: k->eip = (uint32_t)val;
! 86: break;
! 87:
! 88: case CTX_KARG:
! 89: /* Kernel mode argument */
! 90: argp = (uint32_t *)(k->esp + sizeof(uint32_t) * 2);
! 91: *argp = (uint32_t)val;
! 92: break;
! 93:
! 94: case CTX_USTACK:
! 95: /* User mode stack pointer */
1.1 nbrk 96: u = ctx->uregs;
1.1.1.1.2.1! nbrk 97: u->esp = (uint32_t)val;
! 98: u->ss = (uint32_t)(USER_DS | 3); /* fail safe */
! 99: break;
! 100:
! 101: case CTX_UENTRY:
! 102: /* User mode program counter */
! 103: u = ctx->uregs;
! 104: u->eip = (uint32_t)val;
! 105: u->cs = (uint32_t)(USER_CS | 3);
! 106: u->ds = u->es = (uint32_t)(USER_DS | 3);
! 107: u->eflags = (uint32_t)(EFL_IF | EFL_IOPL_KERN);
1.1 nbrk 108: u->eax = u->ebx = u->ecx = u->edx =
1.1.1.1.2.1! nbrk 109: u->edi = u->esi = u->ebp = 0x12345678;
1.1 nbrk 110: break;
1.1.1.1.2.1! nbrk 111:
! 112: case CTX_UARG:
! 113: /* User mode argument */
1.1 nbrk 114: u = ctx->uregs;
1.1.1.1.2.1! nbrk 115: argp = (uint32_t *)(u->esp + sizeof(uint32_t));
! 116: umem_copyout(&val, argp, sizeof(uint32_t));
1.1 nbrk 117: break;
1.1.1.1.2.1! nbrk 118:
! 119: default:
! 120: /* invalid */
1.1 nbrk 121: break;
122: }
1.1.1.1.2.1! nbrk 123:
1.1 nbrk 124: }
125:
126: /*
127: * Switch to new context
128: *
1.1.1.1.2.1! nbrk 129: * Kernel mode registers and kernel stack pointer are switched to
! 130: * the next context.
1.1 nbrk 131: *
1.1.1.1.2.1! nbrk 132: * We don't use x86 task switch mechanism to minimize the context
! 133: * space. The system has only one TSS(task state segment), and
! 134: * the context switching is done by changing the register value
! 135: * in this TSS. Processor will reload them automatically when it
! 136: * enters to the kernel mode in next time.
1.1 nbrk 137: *
138: * It is assumed all interrupts are disabled by caller.
139: *
140: * TODO: FPU context is not switched as of now.
141: */
142: void
143: context_switch(context_t prev, context_t next)
144: {
145: /* Set kernel stack pointer in TSS (esp0). */
1.1.1.1.2.1! nbrk 146: tss_set((uint32_t)next->esp0);
1.1 nbrk 147:
148: /* Save the previous context, and restore the next context */
149: cpu_switch(&prev->kregs, &next->kregs);
150: }
151:
152: /*
153: * Save user mode context to handle exceptions.
154: *
1.1.1.1.2.1! nbrk 155: * Copy current user mode registers in the kernel stack to the
! 156: * user mode stack. The user stack pointer is adjusted for this
! 157: * area. So that the exception handler can get the register
! 158: * state of the target thread.
1.1 nbrk 159: *
160: * It builds arguments for the exception handler in the following
161: * format.
162: *
163: * void exception_handler(int exc, void *regs);
164: */
165: void
1.1.1.1.2.1! nbrk 166: context_save(context_t ctx)
1.1 nbrk 167: {
168: struct cpu_regs *cur, *sav;
169:
170: /* Copy current register context into user mode stack */
171: cur = ctx->uregs;
172: sav = (struct cpu_regs *)(cur->esp - sizeof(struct cpu_regs));
1.1.1.1.2.1! nbrk 173: *sav = *cur;
! 174:
! 175: ctx->saved_regs = sav;
1.1 nbrk 176:
1.1.1.1.2.1! nbrk 177: /* Adjust stack pointer */
! 178: cur->esp = (uint32_t)(sav - (sizeof(u_long) * 2));
1.1 nbrk 179: }
180:
181: /*
182: * Restore register context to return from the exception handler.
183: */
184: void
1.1.1.1.2.1! nbrk 185: context_restore(context_t ctx)
1.1 nbrk 186: {
187: struct cpu_regs *cur;
188:
189: /* Restore user mode context */
190: cur = ctx->uregs;
1.1.1.1.2.1! nbrk 191: *cur = *ctx->saved_regs;
1.1 nbrk 192:
193: /* Correct some registers for fail safe */
1.1.1.1.2.1! nbrk 194: cur->cs = (uint32_t)(USER_CS | 3);
! 195: cur->ss = cur->ds = cur->es = (uint32_t)(USER_DS | 3);
1.1 nbrk 196: cur->eflags |= EFL_IF;
197:
198: ASSERT(cur->eip && user_area(cur->eip));
199: ASSERT(cur->esp && user_area(cur->esp));
200: }
CVSweb