00001 /* 00002 * Copyright (c) 2009 00003 * The President and Fellows of Harvard College. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the University nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 */ 00029 00030 #ifndef _CPU_H_ 00031 #define _CPU_H_ 00032 00033 00034 #include <spinlock.h> 00035 #include <threadlist.h> 00036 #include <machine/vm.h> /* for TLBSHOOTDOWN_MAX */ 00037 00038 00039 /* 00040 * Per-cpu structure 00041 * 00042 * Note: curcpu is defined by <current.h>. 00043 * 00044 * cpu->c_self should always be used when *using* the address of curcpu 00045 * (as opposed to merely dereferencing it) in case curcpu is defined as 00046 * a pointer with a fixed address and a per-cpu mapping in the MMU. 00047 */ 00048 00049 struct cpu { 00050 /* 00051 * Fixed after allocation. 00052 */ 00053 struct cpu *c_self; /* Canonical address of this struct */ 00054 unsigned c_number; /* This cpu's cpu number */ 00055 unsigned c_hardware_number; /* Hardware-defined cpu number */ 00056 00057 /* 00058 * Accessed only by this cpu. 00059 */ 00060 struct thread *c_curthread; /* Current thread on cpu */ 00061 struct threadlist c_zombies; /* List of exited threads */ 00062 unsigned c_hardclocks; /* Counter of hardclock() calls */ 00063 00064 /* 00065 * Accessed by other cpus. 00066 * Protected by the runqueue lock. 00067 */ 00068 bool c_isidle; /* True if this cpu is idle */ 00069 struct threadlist c_runqueue; /* Run queue for this cpu */ 00070 struct spinlock c_runqueue_lock; 00071 00072 /* 00073 * Accessed by other cpus. 00074 * Protected by the IPI lock. 00075 * 00076 * If c_numshootdown is -1 (TLBSHOOTDOWN_ALL), all mappings 00077 * should be invalidated. This is used if more than 00078 * TLBSHOOTDOWN_MAX mappings are going to be invalidated at 00079 * once. TLBSHOOTDOWN_MAX is MD and chosen based on when it 00080 * becomes more efficient just to flush the whole TLB. 00081 * 00082 * struct tlbshootdown is machine-dependent and might 00083 * reasonably be either an address space and vaddr pair, or a 00084 * paddr, or something else. 00085 */ 00086 uint32_t c_ipi_pending; /* One bit for each IPI number */ 00087 struct tlbshootdown c_shootdown[TLBSHOOTDOWN_MAX]; 00088 int c_numshootdown; 00089 struct spinlock c_ipi_lock; 00090 }; 00091 00092 #define TLBSHOOTDOWN_ALL (-1) 00093 00094 /* 00095 * Initialization functions. 00096 * 00097 * cpu_create creates a cpu; it is suitable for calling from driver- 00098 * or bus-specific code that looks for secondary CPUs. 00099 * 00100 * cpu_create calls cpu_machdep_init. 00101 * 00102 * cpu_start_secondary is the platform-dependent assembly language 00103 * entry point for new CPUs; it can be found in start.S. It calls 00104 * cpu_hatch after having claimed the startup stack and thread created 00105 * for the cpu. 00106 */ 00107 struct cpu *cpu_create(unsigned hardware_number); 00108 void cpu_machdep_init(struct cpu *); 00109 /*ASMLINKAGE*/ void cpu_start_secondary(void); 00110 void cpu_hatch(unsigned software_number); 00111 00112 /* 00113 * Return a string describing the CPU type. 00114 */ 00115 const char *cpu_identify(void); 00116 00117 /* 00118 * Hardware-level interrupt on/off, for the current CPU. 00119 * 00120 * These should only be used by the spl code. 00121 */ 00122 void cpu_irqoff(void); 00123 void cpu_irqon(void); 00124 00125 /* 00126 * Idle or shut down (respectively) the processor. 00127 * 00128 * cpu_idle() sits around (in a low-power state if possible) until it 00129 * thinks something interesting may have happened, such as an 00130 * interrupt. Then it returns. (It may be wrong, so it should always 00131 * be called in a loop checking some other condition.) It must be 00132 * called with interrupts off to avoid race conditions, although 00133 * interrupts may be delivered before it returns. 00134 * 00135 * cpu_halt sits around (in a low-power state if possible) until the 00136 * external reset is pushed. Interrupts should be disabled. It does 00137 * not return. It should not allow interrupts to be delivered. 00138 */ 00139 void cpu_idle(void); 00140 void cpu_halt(void); 00141 00142 /* 00143 * Interprocessor interrupts. 00144 * 00145 * From time to time it is necessary to poke another CPU. System 00146 * boards of multiprocessor machines provide a way to do this. 00147 * 00148 * TLB shootdown is done by the VM system when more than one processor 00149 * has (or may have) a page mapped in the MMU and it is being changed 00150 * or otherwise needs to be invalidated across all CPUs. 00151 * 00152 * ipi_send sends an IPI to one CPU. 00153 * ipi_broadcast sends an IPI to all CPUs except the current one. 00154 * ipi_tlbshootdown is like ipi_send but carries TLB shootdown data. 00155 * 00156 * interprocessor_interrupt is called on the target CPU when an IPI is 00157 * received. 00158 */ 00159 00160 /* IPI types */ 00161 #define IPI_PANIC 0 /* System has called panic() */ 00162 #define IPI_OFFLINE 1 /* CPU is requested to go offline */ 00163 #define IPI_UNIDLE 2 /* Runnable threads are available */ 00164 #define IPI_TLBSHOOTDOWN 3 /* MMU mapping(s) need invalidation */ 00165 00166 void ipi_send(struct cpu *target, int code); 00167 void ipi_broadcast(int code); 00168 void ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping); 00169 00170 void interprocessor_interrupt(void); 00171 00172 00173 #endif /* _CPU_H_ */