1 /* $NetBSD: cpu.c,v 1.110 2014/04/15 12:22:49 macallan Exp $ */ 2 3 /* 4 * Copyright (c) 1996 5 * The President and Fellows of Harvard College. All rights reserved. 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This software was developed by the Computer Systems Engineering group 10 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 11 * contributed to Berkeley. 12 * 13 * All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Harvard University. 16 * This product includes software developed by the University of 17 * California, Lawrence Berkeley Laboratory. 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions 21 * are met: 22 * 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 2. Redistributions in binary form must reproduce the above copyright 26 * notice, this list of conditions and the following disclaimer in the 27 * documentation and/or other materials provided with the distribution. 28 * 3. All advertising materials mentioning features or use of this software 29 * must display the following acknowledgement: 30 * This product includes software developed by Aaron Brown and 31 * Harvard University. 32 * This product includes software developed by the University of 33 * California, Berkeley and its contributors. 34 * 4. Neither the name of the University nor the names of its contributors 35 * may be used to endorse or promote products derived from this software 36 * without specific prior written permission. 37 * 38 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 41 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 48 * SUCH DAMAGE. 49 * 50 * @(#)cpu.c 8.5 (Berkeley) 11/23/93 51 * 52 */ 53 54 #include <sys/cdefs.h> 55 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.110 2014/04/15 12:22:49 macallan Exp $"); 56 57 #include "opt_multiprocessor.h" 58 59 #include <sys/param.h> 60 #include <sys/systm.h> 61 #include <sys/device.h> 62 #include <sys/kernel.h> 63 #include <sys/reboot.h> 64 #include <sys/cpu.h> 65 66 #include <uvm/uvm.h> 67 68 #include <machine/autoconf.h> 69 #include <machine/cpu.h> 70 #include <machine/reg.h> 71 #include <machine/trap.h> 72 #include <machine/pmap.h> 73 #include <machine/sparc64.h> 74 #include <machine/openfirm.h> 75 76 #include <sparc64/sparc64/cache.h> 77 #ifdef SUN4V 78 #include <sparc64/hypervisor.h> 79 #endif 80 81 int ecache_min_line_size; 82 83 /* Linked list of all CPUs in system. */ 84 #if defined(MULTIPROCESSOR) 85 int sparc_ncpus = 0; 86 #endif 87 struct cpu_info *cpus = NULL; 88 89 volatile sparc64_cpuset_t cpus_active;/* set of active cpus */ 90 struct cpu_bootargs *cpu_args; /* allocated very early in pmap_bootstrap. */ 91 struct pool_cache *fpstate_cache; 92 93 static struct cpu_info *alloc_cpuinfo(u_int); 94 95 /* The following are used externally (sysctl_hw). */ 96 char machine[] = MACHINE; /* from <machine/param.h> */ 97 char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */ 98 99 /* These are used in locore.s, and are maximums */ 100 int dcache_line_size; 101 int dcache_size; 102 int icache_line_size; 103 int icache_size; 104 105 #ifdef MULTIPROCESSOR 106 static const char *ipi_evcnt_names[IPI_EVCNT_NUM] = IPI_EVCNT_NAMES; 107 #endif 108 109 static void cpu_reset_fpustate(void); 110 111 volatile int sync_tick = 0; 112 113 /* The CPU configuration driver. */ 114 void cpu_attach(device_t, device_t, void *); 115 int cpu_match(device_t, cfdata_t, void *); 116 117 CFATTACH_DECL_NEW(cpu, 0, cpu_match, cpu_attach, NULL, NULL); 118 119 static int 120 upaid_from_node(u_int cpu_node) 121 { 122 int portid; 123 124 if (OF_getprop(cpu_node, "upa-portid", &portid, sizeof(portid)) <= 0 && 125 OF_getprop(cpu_node, "portid", &portid, sizeof(portid)) <= 0) 126 panic("cpu node w/o upa-portid"); 127 128 return portid; 129 } 130 131 struct cpu_info * 132 alloc_cpuinfo(u_int cpu_node) 133 { 134 paddr_t pa0, pa; 135 vaddr_t va, va0; 136 vsize_t sz = 8 * PAGE_SIZE; 137 int portid; 138 struct cpu_info *cpi, *ci; 139 extern paddr_t cpu0paddr; 140 141 /* 142 * Check for UPAID in the cpus list. 143 */ 144 portid = upaid_from_node(cpu_node); 145 146 for (cpi = cpus; cpi != NULL; cpi = cpi->ci_next) 147 if (cpi->ci_cpuid == portid) 148 return cpi; 149 150 /* Allocate the aligned VA and determine the size. */ 151 va = uvm_km_alloc(kernel_map, sz, 8 * PAGE_SIZE, UVM_KMF_VAONLY); 152 if (!va) 153 panic("alloc_cpuinfo: no virtual space"); 154 va0 = va; 155 156 pa0 = cpu0paddr; 157 cpu0paddr += sz; 158 159 for (pa = pa0; pa < cpu0paddr; pa += PAGE_SIZE, va += PAGE_SIZE) 160 pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0); 161 162 pmap_update(pmap_kernel()); 163 164 cpi = (struct cpu_info *)(va0 + CPUINFO_VA - INTSTACK); 165 166 memset((void *)va0, 0, sz); 167 168 /* 169 * Initialize cpuinfo structure. 170 * 171 * Arrange pcb, idle stack and interrupt stack in the same 172 * way as is done for the boot CPU in pmap.c. 173 */ 174 cpi->ci_next = NULL; 175 cpi->ci_curlwp = NULL; 176 cpi->ci_cpuid = portid; 177 cpi->ci_fplwp = NULL; 178 cpi->ci_eintstack = NULL; 179 cpi->ci_spinup = NULL; 180 cpi->ci_paddr = pa0; 181 cpi->ci_self = cpi; 182 #ifdef SUN4V 183 if (CPU_ISSUN4V) 184 cpi->ci_mmfsa = pa0; 185 #endif 186 cpi->ci_node = cpu_node; 187 cpi->ci_idepth = -1; 188 memset(cpi->ci_intrpending, -1, sizeof(cpi->ci_intrpending)); 189 190 /* 191 * Finally, add itself to the list of active cpus. 192 */ 193 for (ci = cpus; ci->ci_next != NULL; ci = ci->ci_next) 194 ; 195 #ifdef MULTIPROCESSOR 196 ci->ci_next = cpi; 197 #endif 198 return (cpi); 199 } 200 201 int 202 cpu_match(device_t parent, cfdata_t cf, void *aux) 203 { 204 struct mainbus_attach_args *ma = aux; 205 206 if (strcmp(cf->cf_name, ma->ma_name) != 0) 207 return 0; 208 209 /* 210 * If we are going to only attach a single cpu, make sure 211 * to pick the one we are running on right now. 212 */ 213 if (upaid_from_node(ma->ma_node) != CPU_UPAID) { 214 #ifdef MULTIPROCESSOR 215 if (boothowto & RB_MD1) 216 #endif 217 return 0; 218 } 219 220 return 1; 221 } 222 223 static void 224 cpu_reset_fpustate(void) 225 { 226 struct fpstate64 *fpstate; 227 struct fpstate64 fps[2]; 228 229 /* This needs to be 64-byte aligned */ 230 fpstate = ALIGNFPSTATE(&fps[1]); 231 232 /* 233 * Get the FSR and clear any exceptions. If we do not unload 234 * the queue here and it is left over from a previous crash, we 235 * will panic in the first loadfpstate(), due to a sequence error, 236 * so we need to dump the whole state anyway. 237 */ 238 fpstate->fs_fsr = 7 << FSR_VER_SHIFT; /* 7 is reserved for "none" */ 239 savefpstate(fpstate); 240 } 241 242 /* 243 * Attach the CPU. 244 * Discover interesting goop about the virtual address cache 245 * (slightly funny place to do it, but this is where it is to be found). 246 */ 247 void 248 cpu_attach(device_t parent, device_t dev, void *aux) 249 { 250 int node; 251 long clk, sclk = 0; 252 struct mainbus_attach_args *ma = aux; 253 struct cpu_info *ci; 254 const char *sep; 255 register int i, l; 256 int bigcache, cachesize; 257 char buf[100]; 258 int totalsize = 0; 259 int linesize, dcachesize, icachesize; 260 261 /* tell them what we have */ 262 node = ma->ma_node; 263 264 /* 265 * Allocate cpu_info structure if needed. 266 */ 267 ci = alloc_cpuinfo((u_int)node); 268 269 /* 270 * Only do this on the boot cpu. Other cpu's call 271 * cpu_reset_fpustate() from cpu_hatch() before they 272 * call into the idle loop. 273 * For other cpus, we need to call mi_cpu_attach() 274 * and complete setting up cpcb. 275 */ 276 if (ci->ci_flags & CPUF_PRIMARY) { 277 fpstate_cache = pool_cache_init(sizeof(struct fpstate64), 278 SPARC64_BLOCK_SIZE, 0, 0, "fpstate", 279 NULL, IPL_NONE, NULL, NULL, NULL); 280 cpu_reset_fpustate(); 281 } 282 #ifdef MULTIPROCESSOR 283 else { 284 mi_cpu_attach(ci); 285 ci->ci_cpcb = lwp_getpcb(ci->ci_data.cpu_idlelwp); 286 } 287 for (i = 0; i < IPI_EVCNT_NUM; ++i) 288 evcnt_attach_dynamic(&ci->ci_ipi_evcnt[i], EVCNT_TYPE_INTR, 289 NULL, device_xname(dev), ipi_evcnt_names[i]); 290 #endif 291 evcnt_attach_dynamic(&ci->ci_tick_evcnt, EVCNT_TYPE_INTR, NULL, 292 device_xname(dev), "timer"); 293 mutex_init(&ci->ci_ctx_lock, MUTEX_SPIN, IPL_VM); 294 295 clk = prom_getpropint(node, "clock-frequency", 0); 296 if (clk == 0) { 297 /* 298 * Try to find it in the OpenPROM root... 299 */ 300 clk = prom_getpropint(findroot(), "clock-frequency", 0); 301 } 302 if (clk) { 303 /* Tell OS what frequency we run on */ 304 ci->ci_cpu_clockrate[0] = clk; 305 ci->ci_cpu_clockrate[1] = clk / 1000000; 306 } 307 308 sclk = prom_getpropint(findroot(), "stick-frequency", 0); 309 310 ci->ci_system_clockrate[0] = sclk; 311 ci->ci_system_clockrate[1] = sclk / 1000000; 312 313 snprintf(buf, sizeof buf, "%s @ %s MHz", 314 prom_getpropstring(node, "name"), clockfreq(clk / 1000)); 315 cpu_setmodel("%s (%s)", machine_model, buf); 316 317 aprint_normal(": %s, UPA id %d\n", buf, ci->ci_cpuid); 318 aprint_naive("\n"); 319 320 if (ci->ci_system_clockrate[0] != 0) { 321 aprint_normal_dev(dev, "system tick frequency %d MHz\n", 322 (int)ci->ci_system_clockrate[1]); 323 } 324 aprint_normal_dev(dev, ""); 325 326 bigcache = 0; 327 328 icachesize = prom_getpropint(node, "icache-size", 0); 329 if (icachesize > icache_size) 330 icache_size = icachesize; 331 linesize = l = prom_getpropint(node, "icache-line-size", 0); 332 if (linesize > icache_line_size) 333 icache_line_size = linesize; 334 335 for (i = 0; (1 << i) < l && l; i++) 336 /* void */; 337 if ((1 << i) != l && l) 338 panic("bad icache line size %d", l); 339 totalsize = icachesize; 340 if (totalsize == 0) 341 totalsize = l * 342 prom_getpropint(node, "icache-nlines", 64) * 343 prom_getpropint(node, "icache-associativity", 1); 344 345 cachesize = totalsize / 346 prom_getpropint(node, "icache-associativity", 1); 347 bigcache = cachesize; 348 349 sep = ""; 350 if (totalsize > 0) { 351 aprint_normal("%s%ldK instruction (%ld b/l)", sep, 352 (long)totalsize/1024, 353 (long)linesize); 354 sep = ", "; 355 } 356 357 dcachesize = prom_getpropint(node, "dcache-size", 0); 358 if (dcachesize > dcache_size) 359 dcache_size = dcachesize; 360 linesize = l = prom_getpropint(node, "dcache-line-size", 0); 361 if (linesize > dcache_line_size) 362 dcache_line_size = linesize; 363 364 for (i = 0; (1 << i) < l && l; i++) 365 /* void */; 366 if ((1 << i) != l && l) 367 panic("bad dcache line size %d", l); 368 totalsize = dcachesize; 369 if (totalsize == 0) 370 totalsize = l * 371 prom_getpropint(node, "dcache-nlines", 128) * 372 prom_getpropint(node, "dcache-associativity", 1); 373 374 cachesize = totalsize / 375 prom_getpropint(node, "dcache-associativity", 1); 376 if (cachesize > bigcache) 377 bigcache = cachesize; 378 379 if (totalsize > 0) { 380 aprint_normal("%s%ldK data (%ld b/l)", sep, 381 (long)totalsize/1024, 382 (long)linesize); 383 sep = ", "; 384 } 385 386 linesize = l = 387 prom_getpropint(node, "ecache-line-size", 0); 388 for (i = 0; (1 << i) < l && l; i++) 389 /* void */; 390 if ((1 << i) != l && l) 391 panic("bad ecache line size %d", l); 392 totalsize = prom_getpropint(node, "ecache-size", 0); 393 if (totalsize == 0) 394 totalsize = l * 395 prom_getpropint(node, "ecache-nlines", 32768) * 396 prom_getpropint(node, "ecache-associativity", 1); 397 398 cachesize = totalsize / 399 prom_getpropint(node, "ecache-associativity", 1); 400 if (cachesize > bigcache) 401 bigcache = cachesize; 402 403 if (totalsize > 0) { 404 aprint_normal("%s%ldK external (%ld b/l)", sep, 405 (long)totalsize/1024, 406 (long)linesize); 407 } 408 aprint_normal("\n"); 409 410 if (ecache_min_line_size == 0 || 411 linesize < ecache_min_line_size) 412 ecache_min_line_size = linesize; 413 414 /* 415 * Now that we know the size of the largest cache on this CPU, 416 * re-color our pages. 417 */ 418 uvm_page_recolor(atop(bigcache)); /* XXX */ 419 420 } 421 422 int 423 cpu_myid(void) 424 { 425 char buf[32]; 426 int impl; 427 428 #ifdef SUN4V 429 if (CPU_ISSUN4V) { 430 uint64_t myid; 431 hv_cpu_myid(&myid); 432 return myid; 433 } 434 #endif 435 if (OF_getprop(findroot(), "name", buf, sizeof(buf)) > 0 && 436 strcmp(buf, "SUNW,Ultra-Enterprise-10000") == 0) 437 return lduwa(0x1fff40000d0UL, ASI_PHYS_NON_CACHED); 438 impl = (getver() & VER_IMPL) >> VER_IMPL_SHIFT; 439 switch (impl) { 440 case IMPL_OLYMPUS_C: 441 case IMPL_JUPITER: 442 return CPU_JUPITERID; 443 case IMPL_CHEETAH: 444 case IMPL_CHEETAH_PLUS: 445 case IMPL_JAGUAR: 446 case IMPL_PANTHER: 447 return CPU_FIREPLANEID; 448 default: 449 return CPU_UPAID; 450 } 451 } 452 453 #if defined(MULTIPROCESSOR) 454 vaddr_t cpu_spinup_trampoline; 455 456 /* 457 * Start secondary processors in motion. 458 */ 459 void 460 cpu_boot_secondary_processors(void) 461 { 462 int i, pstate; 463 struct cpu_info *ci; 464 465 sync_tick = 0; 466 467 sparc64_ipi_init(); 468 469 if (boothowto & RB_MD1) { 470 cpus[0].ci_next = NULL; 471 sparc_ncpus = ncpu = ncpuonline = 1; 472 return; 473 } 474 475 for (ci = cpus; ci != NULL; ci = ci->ci_next) { 476 if (ci->ci_cpuid == CPU_UPAID) 477 continue; 478 479 cpu_pmap_prepare(ci, false); 480 cpu_args->cb_node = ci->ci_node; 481 cpu_args->cb_cpuinfo = ci->ci_paddr; 482 membar_Sync(); 483 484 /* Disable interrupts and start another CPU. */ 485 pstate = getpstate(); 486 setpstate(PSTATE_KERN); 487 488 prom_startcpu(ci->ci_node, (void *)cpu_spinup_trampoline, 0); 489 490 for (i = 0; i < 2000; i++) { 491 membar_Sync(); 492 if (CPUSET_HAS(cpus_active, ci->ci_index)) 493 break; 494 delay(10000); 495 } 496 497 /* synchronize %tick ( to some degree at least ) */ 498 delay(1000); 499 sync_tick = 1; 500 membar_Sync(); 501 settick(0); 502 if (ci->ci_system_clockrate[0] != 0) 503 setstick(0); 504 505 setpstate(pstate); 506 507 if (!CPUSET_HAS(cpus_active, ci->ci_index)) 508 printf("cpu%d: startup failed\n", ci->ci_cpuid); 509 } 510 } 511 512 void 513 cpu_hatch(void) 514 { 515 char *v = (char*)CPUINFO_VA; 516 int i; 517 518 for (i = 0; i < 4*PAGE_SIZE; i += sizeof(long)) 519 flush(v + i); 520 521 cpu_pmap_init(curcpu()); 522 CPUSET_ADD(cpus_active, cpu_number()); 523 cpu_reset_fpustate(); 524 curlwp = curcpu()->ci_data.cpu_idlelwp; 525 membar_Sync(); 526 527 /* wait for the boot CPU to flip the switch */ 528 while (sync_tick == 0) { 529 /* we do nothing here */ 530 } 531 settick(0); 532 if (curcpu()->ci_system_clockrate[0] != 0) { 533 setstick(0); 534 stickintr_establish(PIL_CLOCK, stickintr); 535 } else { 536 tickintr_establish(PIL_CLOCK, tickintr); 537 } 538 spl0(); 539 } 540 #endif /* MULTIPROCESSOR */ 541