[BACK]Return to context.c CVS log [TXT][DIR] Up to [local] / prex-old / sys / arch / i386 / i386

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