Prex Home / Browse Source - Prex Version: 0.9.0

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

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