123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /*
- * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
- * The President and Fellows of Harvard College.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- /*
- * CPU control functions.
- */
- #include <types.h>
- #include <lib.h>
- #include <mips/specialreg.h>
- #include <mips/trapframe.h>
- #include <platform/maxcpus.h>
- #include <cpu.h>
- #include <thread.h>
- ////////////////////////////////////////////////////////////
- /*
- * Startup and exception-time stack hook.
- *
- * The MIPS lacks a good way to find the current CPU, current thread,
- * or current thread stack upon trap entry from user mode. To deal
- * with this, we store the CPU number (our number, not the hardware
- * number) in a nonessential field in the MMU, which is about the only
- * place possible, and then use that to index cpustacks[]. This gets
- * us the value to load as the stack pointer. We can then also load
- * curthread from cputhreads[] by parallel indexing.
- *
- * These arrays are also used to start up new CPUs, for roughly the
- * same reasons.
- */
- vaddr_t cpustacks[MAXCPUS];
- vaddr_t cputhreads[MAXCPUS];
- /*
- * Do machine-dependent initialization of the cpu structure or things
- * associated with a new cpu. Note that we're not running on the new
- * cpu when this is called.
- */
- void
- cpu_machdep_init(struct cpu *c)
- {
- vaddr_t stackpointer;
- KASSERT(c->c_number < MAXCPUS);
- if (c->c_curthread->t_stack == NULL) {
- /* boot cpu; don't need to do anything here */
- }
- else {
- /*
- * Stick the stack in cpustacks[], and thread pointer
- * in cputhreads[].
- */
- /* stack base address */
- stackpointer = (vaddr_t) c->c_curthread->t_stack;
- /* since stacks grow down, get the top */
- stackpointer += STACK_SIZE;
- cpustacks[c->c_number] = stackpointer;
- cputhreads[c->c_number] = (vaddr_t)c->c_curthread;
- }
- }
- ////////////////////////////////////////////////////////////
- /*
- * Return the type name of the currently running CPU.
- */
- const char *
- cpu_identify(void)
- {
- /* XXX Ought to be more sophisticated. */
- return "MIPS r3000";
- }
- ////////////////////////////////////////////////////////////
- /*
- * Interrupt control.
- *
- * While the mips actually has on-chip interrupt priority masking, in
- * the interests of simplicity, we don't use it. Instead we use
- * coprocessor 0 register 12 (the system coprocessor "status"
- * register) bit 0, IEc, which is the global interrupt enable flag.
- * (IEc stands for interrupt-enable-current.)
- */
- /*
- * gcc inline assembly to get at the status register.
- *
- * Pipeline hazards:
- * - there must be at least one cycle between GET_STATUS
- * and SET_STATUS;
- * - it may take up to three cycles after SET_STATUS for the
- * interrupt state to really change.
- *
- * These considerations do not (currently) apply to System/161,
- * however.
- */
- #define GET_STATUS(x) __asm volatile("mfc0 %0,$12" : "=r" (x))
- #define SET_STATUS(x) __asm volatile("mtc0 %0,$12" :: "r" (x))
- /*
- * Interrupts on.
- */
- void
- cpu_irqon(void)
- {
- uint32_t x;
- GET_STATUS(x);
- x |= CST_IEc;
- SET_STATUS(x);
- }
- /*
- * Interrupts off.
- */
- void
- cpu_irqoff(void)
- {
- uint32_t x;
- GET_STATUS(x);
- x &= ~(uint32_t)CST_IEc;
- SET_STATUS(x);
- }
- /*
- * Used below.
- */
- static
- void
- cpu_irqonoff(void)
- {
- uint32_t x, xon, xoff;
- GET_STATUS(x);
- xon = x | CST_IEc;
- xoff = x & ~(uint32_t)CST_IEc;
- SET_STATUS(xon);
- __asm volatile("nop; nop; nop; nop");
- SET_STATUS(xoff);
- }
- ////////////////////////////////////////////////////////////
- /*
- * Idling.
- */
- /*
- * gcc inline assembly for the WAIT instruction.
- *
- * mips r2k/r3k has no idle instruction at all.
- *
- * However, to avoid completely overloading the computing cluster, we
- * appropriate the mips32 WAIT instruction.
- */
- static
- inline
- void
- wait(void)
- {
- /*
- * The WAIT instruction goes into powersave mode until an
- * interrupt is trying to occur.
- *
- * Then switch interrupts on and off again, so we actually
- * take the interrupt.
- *
- * Note that the precise behavior of this instruction in the
- * System/161 simulator is partly guesswork. This code may not
- * work on a real mips.
- */
- __asm volatile(
- ".set push;" /* save assembler mode */
- ".set mips32;" /* allow MIPS32 instructions */
- ".set volatile;" /* avoid unwanted optimization */
- "wait;" /* suspend until interrupted */
- ".set pop" /* restore assembler mode */
- );
- }
- /*
- * Idle the processor until something happens.
- */
- void
- cpu_idle(void)
- {
- wait();
- cpu_irqonoff();
- }
- /*
- * Halt the CPU permanently.
- */
- void
- cpu_halt(void)
- {
- cpu_irqoff();
- while (1) {
- wait();
- }
- }
|