Prex Home / Browse Source - Prex Version: 0.9.0

root/bsp/hal/ppc/arch/context.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. context_set
  2. context_switch
  3. context_save
  4. context_restore
  5. context_dump

   1 /*-
   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 }

/* [<][>][^][v][top][bottom][index][help] */