cpu.c 6.0 KB

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