mp_machdep.c (91066) | mp_machdep.c (91617) |
---|---|
1/*- 2 * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 38 unchanged lines hidden (view full) --- 47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 * SUCH DAMAGE. 54 * | 1/*- 2 * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 38 unchanged lines hidden (view full) --- 47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 * SUCH DAMAGE. 54 * |
55 * $FreeBSD: head/sys/sparc64/sparc64/mp_machdep.c 91066 2002-02-22 13:32:01Z phk $ | 55 * $FreeBSD: head/sys/sparc64/sparc64/mp_machdep.c 91617 2002-03-04 07:12:36Z jake $ |
56 */ 57 58#include <sys/param.h> 59#include <sys/systm.h> 60#include <sys/lock.h> 61#include <sys/kernel.h> 62#include <sys/ktr.h> 63#include <sys/mutex.h> --- 8 unchanged lines hidden (view full) --- 72#include <vm/vm_extern.h> 73#include <vm/vm_map.h> 74 75#include <dev/ofw/openfirm.h> 76 77#include <machine/asi.h> 78#include <machine/md_var.h> 79#include <machine/smp.h> | 56 */ 57 58#include <sys/param.h> 59#include <sys/systm.h> 60#include <sys/lock.h> 61#include <sys/kernel.h> 62#include <sys/ktr.h> 63#include <sys/mutex.h> --- 8 unchanged lines hidden (view full) --- 72#include <vm/vm_extern.h> 73#include <vm/vm_map.h> 74 75#include <dev/ofw/openfirm.h> 76 77#include <machine/asi.h> 78#include <machine/md_var.h> 79#include <machine/smp.h> |
80#include <machine/tlb.h> |
|
80#include <machine/tte.h> 81 82static ih_func_t cpu_ipi_ast; 83static ih_func_t cpu_ipi_stop; 84 85/* 86 * Argument area used to pass data to non-boot processors as they start up. 87 * This must be statically initialized with a known invalid upa module id, 88 * since the other processors will use it before the boot cpu enters the 89 * kernel. 90 */ 91struct cpu_start_args cpu_start_args = { -1, -1, 0, 0 }; 92 | 81#include <machine/tte.h> 82 83static ih_func_t cpu_ipi_ast; 84static ih_func_t cpu_ipi_stop; 85 86/* 87 * Argument area used to pass data to non-boot processors as they start up. 88 * This must be statically initialized with a known invalid upa module id, 89 * since the other processors will use it before the boot cpu enters the 90 * kernel. 91 */ 92struct cpu_start_args cpu_start_args = { -1, -1, 0, 0 }; 93 |
94vm_offset_t mp_tramp; 95 |
|
93static struct mtx ap_boot_mtx; 94 95u_int mp_boot_mid; 96 | 96static struct mtx ap_boot_mtx; 97 98u_int mp_boot_mid; 99 |
100void cpu_mp_unleash(void *); 101SYSINIT(cpu_mp_unleash, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL); 102 103vm_offset_t 104mp_tramp_alloc(void) 105{ 106 struct tte *tp; 107 char *v; 108 int i; 109 110 v = OF_claim(NULL, PAGE_SIZE, PAGE_SIZE); 111 if (v == NULL) 112 panic("mp_tramp_alloc"); 113 bcopy(mp_tramp_code, v, mp_tramp_code_len); 114 *(u_long *)(v + mp_tramp_tlb_slots) = kernel_tlb_slots; 115 *(u_long *)(v + mp_tramp_func) = (u_long)mp_startup; 116 tp = (struct tte *)(v + mp_tramp_code_len); 117 for (i = 0; i < kernel_tlb_slots; i++) 118 tp[i] = kernel_ttes[i]; 119 for (i = 0; i < PAGE_SIZE; i += sizeof(long)) 120 flush(v + i); 121 return (vm_offset_t)v; 122} 123 |
|
97/* 98 * Probe for other cpus. 99 */ 100int 101cpu_mp_probe(void) 102{ 103 phandle_t child; 104 phandle_t root; --- 9 unchanged lines hidden (view full) --- 114 for (child = OF_child(root); child != 0; child = OF_peer(child)) { 115 if (OF_getprop(child, "device_type", buf, sizeof(buf)) > 0 && 116 strcmp(buf, "cpu") == 0) 117 cpus++; 118 } 119 return (cpus > 1); 120} 121 | 124/* 125 * Probe for other cpus. 126 */ 127int 128cpu_mp_probe(void) 129{ 130 phandle_t child; 131 phandle_t root; --- 9 unchanged lines hidden (view full) --- 141 for (child = OF_child(root); child != 0; child = OF_peer(child)) { 142 if (OF_getprop(child, "device_type", buf, sizeof(buf)) > 0 && 143 strcmp(buf, "cpu") == 0) 144 cpus++; 145 } 146 return (cpus > 1); 147} 148 |
149static void 150sun4u_startcpu(phandle_t cpu, void *func, u_long arg) 151{ 152 static struct { 153 cell_t name; 154 cell_t nargs; 155 cell_t nreturns; 156 cell_t cpu; 157 cell_t func; 158 cell_t arg; 159 } args = { 160 (cell_t)"SUNW,start-cpu", 161 3, 162 0, 163 0, 164 0, 165 0 166 }; 167 168 args.cpu = cpu; 169 args.func = (cell_t)func; 170 args.arg = (cell_t)arg; 171 openfirmware(&args); 172} 173 |
|
122/* 123 * Fire up any non-boot processors. 124 */ 125void 126cpu_mp_start(void) 127{ 128 volatile struct cpu_start_args *csa; 129 struct pcpu *pc; 130 phandle_t child; 131 phandle_t root; | 174/* 175 * Fire up any non-boot processors. 176 */ 177void 178cpu_mp_start(void) 179{ 180 volatile struct cpu_start_args *csa; 181 struct pcpu *pc; 182 phandle_t child; 183 phandle_t root; |
132 vm_offset_t pa; | |
133 vm_offset_t va; 134 char buf[128]; | 184 vm_offset_t va; 185 char buf[128]; |
135 u_long data; 136 u_int mid; | 186 u_int clock; |
137 int cpuid; | 187 int cpuid; |
188 u_int mid; 189 u_long s; |
|
138 139 mtx_init(&ap_boot_mtx, "ap boot", MTX_SPIN); 140 141 intr_setup(PIL_AST, cpu_ipi_ast, -1, NULL, NULL); 142 intr_setup(PIL_RENDEZVOUS, (ih_func_t *)smp_rendezvous_action, 143 -1, NULL, NULL); 144 intr_setup(PIL_STOP, cpu_ipi_stop, -1, NULL, NULL); 145 146 root = OF_peer(0); 147 csa = &cpu_start_args; 148 for (child = OF_child(root); child != 0; child = OF_peer(child)) { 149 if (OF_getprop(child, "device_type", buf, sizeof(buf)) <= 0 || 150 strcmp(buf, "cpu") != 0) 151 continue; 152 if (OF_getprop(child, "upa-portid", &mid, sizeof(mid)) <= 0) 153 panic("cpu_mp_start: can't get module id"); 154 if (mid == mp_boot_mid) 155 continue; | 190 191 mtx_init(&ap_boot_mtx, "ap boot", MTX_SPIN); 192 193 intr_setup(PIL_AST, cpu_ipi_ast, -1, NULL, NULL); 194 intr_setup(PIL_RENDEZVOUS, (ih_func_t *)smp_rendezvous_action, 195 -1, NULL, NULL); 196 intr_setup(PIL_STOP, cpu_ipi_stop, -1, NULL, NULL); 197 198 root = OF_peer(0); 199 csa = &cpu_start_args; 200 for (child = OF_child(root); child != 0; child = OF_peer(child)) { 201 if (OF_getprop(child, "device_type", buf, sizeof(buf)) <= 0 || 202 strcmp(buf, "cpu") != 0) 203 continue; 204 if (OF_getprop(child, "upa-portid", &mid, sizeof(mid)) <= 0) 205 panic("cpu_mp_start: can't get module id"); 206 if (mid == mp_boot_mid) 207 continue; |
208 if (OF_getprop(child, "clock-frequency", &clock, 209 sizeof(clock)) <= 0) 210 panic("cpu_mp_start: can't get clock"); |
|
156 | 211 |
157 /* 158 * Found a non-boot processor. It is currently spinning in 159 * _mp_start, and it has no stack. Allocate a per-cpu page 160 * for it, which it will use as a bootstrap stack, and pass 161 * it through the argument area. 162 */ | 212 csa->csa_state = 0; 213 sun4u_startcpu(child, (void *)mp_tramp, 0); 214 s = intr_disable(); 215 while (csa->csa_state != CPU_CLKSYNC) 216 ; 217 membar(StoreLoad); 218 csa->csa_tick = rd(tick); 219 while (csa->csa_state != CPU_INIT) 220 ; 221 csa->csa_tick = 0; 222 intr_restore(s); 223 |
163 cpuid = mp_ncpus++; | 224 cpuid = mp_ncpus++; |
164 va = kmem_alloc(kernel_map, PAGE_SIZE); 165 pa = pmap_kextract(va); 166 if (pa == 0) 167 panic("cpu_mp_start: pmap_kextract\n"); 168 pc = (struct pcpu *)(va + PAGE_SIZE) - 1; | 225 cpu_identify(csa->csa_ver, clock, cpuid); 226 227 va = kmem_alloc(kernel_map, PCPU_PAGES * PAGE_SIZE); 228 pc = (struct pcpu *)(va + (PCPU_PAGES * PAGE_SIZE)) - 1; |
169 pcpu_init(pc, cpuid, sizeof(*pc)); | 229 pcpu_init(pc, cpuid, sizeof(*pc)); |
230 pc->pc_addr = va; |
|
170 pc->pc_mid = mid; | 231 pc->pc_mid = mid; |
171 data = TD_V | TD_8K | TD_VA_LOW(va) | TD_PA(pa) | 172 TD_L | TD_CP | TD_CV | TD_P | TD_W; | |
173 | 232 |
174 /* 175 * Initialize the argument area to start this cpu. 176 * Note, order is important here. We must set the pcpu pointer 177 * and the tte data before letting it loose. 178 */ 179 csa->csa_data = data; 180 csa->csa_va = va; 181 membar(StoreLoad); 182 csa->csa_mid = mid; 183 csa->csa_state = CPU_STARTING; 184 while (csa->csa_state == CPU_STARTING) 185 membar(StoreLoad); 186 if (csa->csa_state != CPU_STARTED) 187 panic("cpu_mp_start: bad state %d for cpu %d\n", 188 csa->csa_state, mid); 189 csa->csa_state = CPU_BOOTSTRAPING; 190 while (csa->csa_state == CPU_BOOTSTRAPING) 191 membar(StoreLoad); 192 if (csa->csa_state != CPU_BOOTSTRAPPED) 193 panic("cpu_mp_start: bad state %d for cpu %d\n", 194 csa->csa_state, mid); 195 cpu_ipi_send(mid, 0, (u_long)tl_ipi_test, 0); | |
196 all_cpus |= 1 << cpuid; 197 } 198 PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid))); 199} 200 201void 202cpu_mp_announce(void) 203{ | 233 all_cpus |= 1 << cpuid; 234 } 235 PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid))); 236} 237 238void 239cpu_mp_announce(void) 240{ |
204 TODO; | |
205} 206 207void | 241} 242 243void |
208cpu_mp_bootstrap(struct pcpu *pc) | 244cpu_mp_unleash(void *v) |
209{ | 245{ |
210 struct cpu_start_args *csa; | 246 volatile struct cpu_start_args *csa; 247 struct pcpu *pc; 248 vm_offset_t pa; 249 vm_offset_t va; 250 u_int ctx_min; 251 u_int ctx_inc; 252 u_long s; 253 int i; |
211 | 254 |
255 ctx_min = 1; 256 ctx_inc = (8192 - 1) / mp_ncpus; |
|
212 csa = &cpu_start_args; | 257 csa = &cpu_start_args; |
213 CTR1(KTR_SMP, "cpu_mp_bootstrap: cpuid=%d", pc->pc_cpuid); 214 while (csa->csa_state != CPU_BOOTSTRAPING) 215 membar(StoreLoad); 216 cpu_setregs(pc); 217 pmap_map_tsb(); | 258 SLIST_FOREACH(pc, &cpuhead, pc_allcpu) { 259 pc->pc_tlb_ctx = ctx_min; 260 pc->pc_tlb_ctx_min = ctx_min; 261 pc->pc_tlb_ctx_max = ctx_min + ctx_inc; 262 ctx_min += ctx_inc; |
218 | 263 |
219 CTR0(KTR_SMP, "cpu_mp_bootstrap: spinning"); 220 csa->csa_state = CPU_BOOTSTRAPPED; 221 membar(StoreLoad); 222 for (;;) 223 ; | 264 if (pc->pc_cpuid == PCPU_GET(cpuid)) 265 continue; 266 KASSERT(pc->pc_idlethread != NULL, 267 ("cpu_mp_unleash: idlethread")); 268 KASSERT(pc->pc_curthread == pc->pc_idlethread, 269 ("cpu_mp_unleash: curthread")); 270 271 pc->pc_curpcb = pc->pc_curthread->td_pcb; 272 for (i = 0; i < PCPU_PAGES; i++) { 273 va = pc->pc_addr + i * PAGE_SIZE; 274 pa = pmap_kextract(va); 275 if (pa == 0) 276 panic("cpu_mp_unleash: pmap_kextract\n"); 277 csa->csa_ttes[i].tte_vpn = TV_VPN(va); 278 csa->csa_ttes[i].tte_data = TD_V | TD_8K | TD_PA(pa) | 279 TD_L | TD_CP | TD_CV | TD_P | TD_W; 280 } 281 csa->csa_state = 0; 282 csa->csa_mid = pc->pc_mid; 283 s = intr_disable(); 284 while (csa->csa_state != CPU_BOOTSTRAP) 285 ; 286 intr_restore(s); 287 } 288} |
224 | 289 |
225 mtx_lock_spin(&ap_boot_mtx); | 290void 291cpu_mp_bootstrap(struct pcpu *pc) 292{ 293 volatile struct cpu_start_args *csa; |
226 | 294 |
227 CTR1(KTR_SMP, "SMP: AP CPU #%d Launched", PCPU_GET(cpuid)); | 295 csa = &cpu_start_args; 296 pmap_map_tsb(); 297 cpu_setregs(pc); |
228 229 smp_cpus++; | 298 299 smp_cpus++; |
230 231 /* Build our map of 'other' CPUs. */ | |
232 PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid))); | 300 PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid))); |
233 | |
234 printf("SMP: AP CPU #%d Launched!\n", PCPU_GET(cpuid)); 235 | 301 printf("SMP: AP CPU #%d Launched!\n", PCPU_GET(cpuid)); 302 |
236 if (smp_cpus == mp_ncpus) { 237 smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */ 238 smp_active = 1; /* historic */ 239 } | 303 csa->csa_state = CPU_BOOTSTRAP; 304 for (;;) 305 ; |
240 | 306 |
241 mtx_unlock_spin(&ap_boot_mtx); 242 243 /* wait until all the AP's are up */ 244 while (smp_started == 0) 245 ; /* nothing */ 246 | |
247 binuptime(PCPU_PTR(switchtime)); 248 PCPU_SET(switchticks, ticks); 249 250 /* ok, now grab sched_lock and enter the scheduler */ 251 mtx_lock_spin(&sched_lock); 252 cpu_throw(); /* doesn't return */ 253} 254 --- 68 unchanged lines hidden --- | 307 binuptime(PCPU_PTR(switchtime)); 308 PCPU_SET(switchticks, ticks); 309 310 /* ok, now grab sched_lock and enter the scheduler */ 311 mtx_lock_spin(&sched_lock); 312 cpu_throw(); /* doesn't return */ 313} 314 --- 68 unchanged lines hidden --- |