root/kern/arch/mips/thread/cpu.c

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

DEFINITIONS

This source file includes following definitions.
  1. cpu_machdep_init
  2. cpu_identify
  3. cpu_irqon
  4. cpu_irqoff
  5. cpu_irqonoff
  6. wait
  7. cpu_idle
  8. cpu_halt

   1 /*
   2  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
   3  *      The President and Fellows of Harvard College.
   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 University nor the names of its 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 UNIVERSITY 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 UNIVERSITY 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  * CPU control functions.
  32  */
  33 
  34 #include <types.h>
  35 #include <lib.h>
  36 #include <mips/specialreg.h>
  37 #include <mips/trapframe.h>
  38 #include <platform/maxcpus.h>
  39 #include <cpu.h>
  40 #include <thread.h>
  41 
  42 ////////////////////////////////////////////////////////////
  43 
  44 /*
  45  * Startup and exception-time stack hook.
  46  *
  47  * The MIPS lacks a good way to find the current CPU, current thread,
  48  * or current thread stack upon trap entry from user mode. To deal
  49  * with this, we store the CPU number (our number, not the hardware
  50  * number) in a nonessential field in the MMU, which is about the only
  51  * place possible, and then use that to index cpustacks[]. This gets
  52  * us the value to load as the stack pointer. We can then also load
  53  * curthread from cputhreads[] by parallel indexing.
  54  *
  55  * These arrays are also used to start up new CPUs, for roughly the
  56  * same reasons.
  57  */
  58 
  59 vaddr_t cpustacks[MAXCPUS];
  60 vaddr_t cputhreads[MAXCPUS];
  61 
  62 /*
  63  * Do machine-dependent initialization of the cpu structure or things
  64  * associated with a new cpu. Note that we're not running on the new
  65  * cpu when this is called.
  66  */
  67 void
  68 cpu_machdep_init(struct cpu *c)
  69 {
  70         vaddr_t stackpointer;
  71 
  72         KASSERT(c->c_number < MAXCPUS);
  73 
  74         if (c->c_curthread->t_stack == NULL) {
  75                 /* boot cpu; don't need to do anything here */
  76         }
  77         else {
  78                 /*
  79                  * Stick the stack in cpustacks[], and thread pointer
  80                  * in cputhreads[].
  81                  */
  82 
  83                 /* stack base address */
  84                 stackpointer = (vaddr_t) c->c_curthread->t_stack;
  85                 /* since stacks grow down, get the top */
  86                 stackpointer += STACK_SIZE;
  87 
  88                 cpustacks[c->c_number] = stackpointer;
  89                 cputhreads[c->c_number] = (vaddr_t)c->c_curthread;
  90         }
  91 }
  92 
  93 ////////////////////////////////////////////////////////////
  94 
  95 /*
  96  * Return the type name of the currently running CPU.
  97  */
  98 
  99 const char *
 100 cpu_identify(void)
 101 {
 102         /* XXX Ought to be more sophisticated. */
 103         return "MIPS r3000";
 104 }
 105 
 106 ////////////////////////////////////////////////////////////
 107 
 108 /*
 109  * Interrupt control.
 110  *
 111  * While the mips actually has on-chip interrupt priority masking, in
 112  * the interests of simplicity, we don't use it. Instead we use
 113  * coprocessor 0 register 12 (the system coprocessor "status"
 114  * register) bit 0, IEc, which is the global interrupt enable flag.
 115  * (IEc stands for interrupt-enable-current.)
 116  */
 117 
 118 /*
 119  * gcc inline assembly to get at the status register.
 120  *
 121  * Pipeline hazards:
 122  *    - there must be at least one cycle between GET_STATUS
 123  *      and SET_STATUS;
 124  *    - it may take up to three cycles after SET_STATUS for the
 125  *      interrupt state to really change.
 126  *
 127  * These considerations do not (currently) apply to System/161,
 128  * however.
 129  */
 130 #define GET_STATUS(x) __asm volatile("mfc0 %0,$12" : "=r" (x))
 131 #define SET_STATUS(x) __asm volatile("mtc0 %0,$12" :: "r" (x))
 132 
 133 /*
 134  * Interrupts on.
 135  */
 136 void
 137 cpu_irqon(void)
 138 {
 139         uint32_t x;
 140 
 141         GET_STATUS(x);
 142         x |= CST_IEc;
 143         SET_STATUS(x);
 144 }
 145 
 146 /*
 147  * Interrupts off.
 148  */
 149 void
 150 cpu_irqoff(void)
 151 {
 152         uint32_t x;
 153 
 154         GET_STATUS(x);
 155         x &= ~(uint32_t)CST_IEc;
 156         SET_STATUS(x);
 157 }
 158 
 159 /*
 160  * Used below.
 161  */
 162 static
 163 void
 164 cpu_irqonoff(void)
 165 {
 166         uint32_t x, xon, xoff;
 167 
 168         GET_STATUS(x);
 169         xon = x | CST_IEc;
 170         xoff = x & ~(uint32_t)CST_IEc;
 171         SET_STATUS(xon);
 172         __asm volatile("nop; nop; nop; nop");
 173         SET_STATUS(xoff);
 174 }
 175 
 176 ////////////////////////////////////////////////////////////
 177 
 178 /*
 179  * Idling.
 180  */
 181 
 182 /*
 183  * gcc inline assembly for the WAIT instruction.
 184  *
 185  * mips r2k/r3k has no idle instruction at all.
 186  *
 187  * However, to avoid completely overloading the computing cluster, we
 188  * appropriate the mips32 WAIT instruction.
 189  */
 190 
 191 static
 192 inline
 193 void
 194 wait(void)
 195 {
 196         /*
 197          * The WAIT instruction goes into powersave mode until an
 198          * interrupt is trying to occur.
 199          *
 200          * Then switch interrupts on and off again, so we actually
 201          * take the interrupt.
 202          *
 203          * Note that the precise behavior of this instruction in the
 204          * System/161 simulator is partly guesswork. This code may not
 205          * work on a real mips.
 206          */
 207         __asm volatile(
 208                 ".set push;"            /* save assembler mode */
 209                 ".set mips32;"          /* allow MIPS32 instructions */
 210                 ".set volatile;"        /* avoid unwanted optimization */
 211                 "wait;"                 /* suspend until interrupted */
 212                 ".set pop"              /* restore assembler mode */
 213               );
 214 }
 215 
 216 /*
 217  * Idle the processor until something happens.
 218  */
 219 void 
 220 cpu_idle(void)
 221 {
 222         wait();
 223         cpu_irqonoff();
 224 }
 225 
 226 /*
 227  * Halt the CPU permanently.
 228  */
 229 void
 230 cpu_halt(void)
 231 {
 232         cpu_irqoff();
 233         while (1) {
 234                 wait();
 235         }
 236 }

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