1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/machsystm.h> 30 #include <sys/archsystm.h> 31 #include <sys/prom_plat.h> 32 #include <sys/promif.h> 33 #include <sys/vm.h> 34 #include <sys/cpu.h> 35 #include <sys/atomic.h> 36 #include <sys/cpupart.h> 37 #include <sys/disp.h> 38 #include <sys/hypervisor_api.h> 39 #include <sys/traptrace.h> 40 #include <sys/modctl.h> 41 #include <sys/ldoms.h> 42 #include <vm/vm_dep.h> 43 44 #ifdef TRAPTRACE 45 int mach_htraptrace_enable = 1; 46 #else 47 int mach_htraptrace_enable = 0; 48 #endif 49 int htrap_tr0_inuse = 0; 50 extern char htrap_tr0[]; /* prealloc buf for boot cpu */ 51 52 caddr_t mmu_fault_status_area; 53 54 extern void sfmmu_set_tsbs(void); 55 /* 56 * CPU IDLE optimization variables/routines 57 */ 58 static int enable_halt_idle_cpus = 1; 59 60 void 61 setup_trap_table(void) 62 { 63 caddr_t mmfsa_va; 64 extern caddr_t mmu_fault_status_area; 65 mmfsa_va = 66 mmu_fault_status_area + (MMFSA_SIZE * CPU->cpu_id); 67 68 intr_init(CPU); /* init interrupt request free list */ 69 setwstate(WSTATE_KERN); 70 set_mmfsa_scratchpad(mmfsa_va); 71 prom_set_mmfsa_traptable(&trap_table, va_to_pa(mmfsa_va)); 72 sfmmu_set_tsbs(); 73 } 74 75 void 76 phys_install_has_changed(void) 77 { 78 79 } 80 81 /* 82 * Halt the present CPU until awoken via an interrupt 83 */ 84 static void 85 cpu_halt(void) 86 { 87 cpu_t *cpup = CPU; 88 processorid_t cpun = cpup->cpu_id; 89 cpupart_t *cp = cpup->cpu_part; 90 int hset_update = 1; 91 volatile int *p = &cpup->cpu_disp->disp_nrunnable; 92 uint_t s; 93 94 /* 95 * If this CPU is online, and there's multiple CPUs 96 * in the system, then we should notate our halting 97 * by adding ourselves to the partition's halted CPU 98 * bitmap. This allows other CPUs to find/awaken us when 99 * work becomes available. 100 */ 101 if (CPU->cpu_flags & CPU_OFFLINE || ncpus == 1) 102 hset_update = 0; 103 104 /* 105 * Add ourselves to the partition's halted CPUs bitmask 106 * and set our HALTED flag, if necessary. 107 * 108 * When a thread becomes runnable, it is placed on the queue 109 * and then the halted cpuset is checked to determine who 110 * (if anyone) should be awoken. We therefore need to first 111 * add ourselves to the halted cpuset, and then check if there 112 * is any work available. 113 */ 114 if (hset_update) { 115 cpup->cpu_disp_flags |= CPU_DISP_HALTED; 116 membar_producer(); 117 CPUSET_ATOMIC_ADD(cp->cp_mach->mc_haltset, cpun); 118 } 119 120 /* 121 * Check to make sure there's really nothing to do. 122 * Work destined for this CPU may become available after 123 * this check. We'll be notified through the clearing of our 124 * bit in the halted CPU bitmask, and a poke. 125 */ 126 if (disp_anywork()) { 127 if (hset_update) { 128 cpup->cpu_disp_flags &= ~CPU_DISP_HALTED; 129 CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun); 130 } 131 return; 132 } 133 134 /* 135 * We're on our way to being halted. Wait until something becomes 136 * runnable locally or we are awaken (i.e. removed from the halt set). 137 * Note that the call to hv_cpu_yield() can return even if we have 138 * nothing to do. 139 * 140 * Disable interrupts now, so that we'll awaken immediately 141 * after halting if someone tries to poke us between now and 142 * the time we actually halt. 143 * 144 * We check for the presence of our bit after disabling interrupts. 145 * If it's cleared, we'll return. If the bit is cleared after 146 * we check then the poke will pop us out of the halted state. 147 * Also, if the offlined CPU has been brought back on-line, then 148 * we return as well. 149 * 150 * The ordering of the poke and the clearing of the bit by cpu_wakeup 151 * is important. 152 * cpu_wakeup() must clear, then poke. 153 * cpu_halt() must disable interrupts, then check for the bit. 154 * 155 * The check for anything locally runnable is here for performance 156 * and isn't needed for correctness. disp_nrunnable ought to be 157 * in our cache still, so it's inexpensive to check, and if there 158 * is anything runnable we won't have to wait for the poke. 159 * 160 */ 161 s = disable_vec_intr(); 162 while (*p == 0 && 163 ((hset_update && CPU_IN_SET(cp->cp_mach->mc_haltset, cpun)) || 164 (!hset_update && (CPU->cpu_flags & CPU_OFFLINE)))) { 165 (void) hv_cpu_yield(); 166 enable_vec_intr(s); 167 s = disable_vec_intr(); 168 } 169 170 /* 171 * We're no longer halted 172 */ 173 enable_vec_intr(s); 174 if (hset_update) { 175 cpup->cpu_disp_flags &= ~CPU_DISP_HALTED; 176 CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpun); 177 } 178 } 179 180 /* 181 * If "cpu" is halted, then wake it up clearing its halted bit in advance. 182 * Otherwise, see if other CPUs in the cpu partition are halted and need to 183 * be woken up so that they can steal the thread we placed on this CPU. 184 * This function is only used on MP systems. 185 */ 186 static void 187 cpu_wakeup(cpu_t *cpu, int bound) 188 { 189 uint_t cpu_found; 190 int result; 191 cpupart_t *cp; 192 193 cp = cpu->cpu_part; 194 if (CPU_IN_SET(cp->cp_mach->mc_haltset, cpu->cpu_id)) { 195 /* 196 * Clear the halted bit for that CPU since it will be 197 * poked in a moment. 198 */ 199 CPUSET_ATOMIC_DEL(cp->cp_mach->mc_haltset, cpu->cpu_id); 200 /* 201 * We may find the current CPU present in the halted cpuset 202 * if we're in the context of an interrupt that occurred 203 * before we had a chance to clear our bit in cpu_halt(). 204 * Poking ourself is obviously unnecessary, since if 205 * we're here, we're not halted. 206 */ 207 if (cpu != CPU) 208 poke_cpu(cpu->cpu_id); 209 return; 210 } else { 211 /* 212 * This cpu isn't halted, but it's idle or undergoing a 213 * context switch. No need to awaken anyone else. 214 */ 215 if (cpu->cpu_thread == cpu->cpu_idle_thread || 216 cpu->cpu_disp_flags & CPU_DISP_DONTSTEAL) 217 return; 218 } 219 220 /* 221 * No need to wake up other CPUs if the thread we just enqueued 222 * is bound. 223 */ 224 if (bound) 225 return; 226 227 /* 228 * See if there's any other halted CPUs. If there are, then 229 * select one, and awaken it. 230 * It's possible that after we find a CPU, somebody else 231 * will awaken it before we get the chance. 232 * In that case, look again. 233 */ 234 do { 235 CPUSET_FIND(cp->cp_mach->mc_haltset, cpu_found); 236 if (cpu_found == CPUSET_NOTINSET) 237 return; 238 239 ASSERT(cpu_found >= 0 && cpu_found < NCPU); 240 CPUSET_ATOMIC_XDEL(cp->cp_mach->mc_haltset, cpu_found, result); 241 } while (result < 0); 242 243 if (cpu_found != CPU->cpu_id) 244 poke_cpu(cpu_found); 245 } 246 247 void 248 mach_cpu_halt_idle() 249 { 250 if (enable_halt_idle_cpus) { 251 idle_cpu = cpu_halt; 252 disp_enq_thread = cpu_wakeup; 253 } 254 } 255 256 int 257 ndata_alloc_mmfsa(struct memlist *ndata) 258 { 259 size_t size; 260 261 size = MMFSA_SIZE * max_ncpus; 262 mmu_fault_status_area = ndata_alloc(ndata, size, ecache_alignsize); 263 if (mmu_fault_status_area == NULL) 264 return (-1); 265 return (0); 266 } 267 268 void 269 mach_memscrub(void) 270 { 271 /* no memscrub support for sun4v for now */ 272 } 273 274 void 275 mach_fpras() 276 { 277 /* no fpras support for sun4v for now */ 278 } 279 280 void 281 mach_hw_copy_limit(void) 282 { 283 /* HW copy limits set by individual CPU module */ 284 } 285 286 /* 287 * We need to enable soft ring functionality on Niagara platform since 288 * one strand can't handle interrupts for a 1Gb NIC. Set the tunable 289 * ip_squeue_soft_ring by default on this platform. We can also set 290 * ip_threads_per_cpu to track number of threads per core. The variables 291 * themselves are defined in space.c and used by IP module 292 */ 293 extern uint_t ip_threads_per_cpu; 294 extern boolean_t ip_squeue_soft_ring; 295 void 296 startup_platform(void) 297 { 298 ip_squeue_soft_ring = B_TRUE; 299 } 300 301 /* 302 * This function sets up hypervisor traptrace buffer 303 * This routine is called by the boot cpu only 304 */ 305 void 306 mach_htraptrace_setup(int cpuid) 307 { 308 TRAP_TRACE_CTL *ctlp; 309 int bootcpuid = getprocessorid(); /* invoked on boot cpu only */ 310 311 if (mach_htraptrace_enable && ((cpuid != bootcpuid) || 312 !htrap_tr0_inuse)) { 313 ctlp = &trap_trace_ctl[cpuid]; 314 ctlp->d.hvaddr_base = (cpuid == bootcpuid) ? htrap_tr0 : 315 contig_mem_alloc_align(HTRAP_TSIZE, HTRAP_TSIZE); 316 if (ctlp->d.hvaddr_base == NULL) { 317 ctlp->d.hlimit = 0; 318 ctlp->d.hpaddr_base = NULL; 319 cmn_err(CE_WARN, "!cpu%d: failed to allocate HV " 320 "traptrace buffer", cpuid); 321 } else { 322 ctlp->d.hlimit = HTRAP_TSIZE; 323 ctlp->d.hpaddr_base = va_to_pa(ctlp->d.hvaddr_base); 324 } 325 } 326 } 327 328 /* 329 * This function enables or disables the hypervisor traptracing 330 */ 331 void 332 mach_htraptrace_configure(int cpuid) 333 { 334 uint64_t ret; 335 uint64_t prev_buf, prev_bufsize; 336 uint64_t prev_enable; 337 uint64_t size; 338 TRAP_TRACE_CTL *ctlp; 339 340 ctlp = &trap_trace_ctl[cpuid]; 341 if (mach_htraptrace_enable) { 342 if ((ctlp->d.hvaddr_base != NULL) && 343 ((ctlp->d.hvaddr_base != htrap_tr0) || 344 (!htrap_tr0_inuse))) { 345 ret = hv_ttrace_buf_info(&prev_buf, &prev_bufsize); 346 if ((ret == H_EOK) && (prev_bufsize != 0)) { 347 cmn_err(CE_CONT, 348 "!cpu%d: previous HV traptrace buffer of " 349 "size 0x%lx at address 0x%lx", cpuid, 350 prev_bufsize, prev_buf); 351 } 352 353 ret = hv_ttrace_buf_conf(ctlp->d.hpaddr_base, 354 ctlp->d.hlimit / 355 (sizeof (struct htrap_trace_record)), &size); 356 if (ret == H_EOK) { 357 ret = hv_ttrace_enable(\ 358 (uint64_t)TRAP_TENABLE_ALL, &prev_enable); 359 if (ret != H_EOK) { 360 cmn_err(CE_WARN, 361 "!cpu%d: HV traptracing not " 362 "enabled, ta: 0x%x returned error: " 363 "%ld", cpuid, TTRACE_ENABLE, ret); 364 } else { 365 if (ctlp->d.hvaddr_base == htrap_tr0) 366 htrap_tr0_inuse = 1; 367 } 368 } else { 369 cmn_err(CE_WARN, 370 "!cpu%d: HV traptrace buffer not " 371 "configured, ta: 0x%x returned error: %ld", 372 cpuid, TTRACE_BUF_CONF, ret); 373 } 374 /* 375 * set hvaddr_base to NULL when traptrace buffer 376 * registration fails 377 */ 378 if (ret != H_EOK) { 379 ctlp->d.hvaddr_base = NULL; 380 ctlp->d.hlimit = 0; 381 ctlp->d.hpaddr_base = NULL; 382 } 383 } 384 } else { 385 ret = hv_ttrace_buf_info(&prev_buf, &prev_bufsize); 386 if ((ret == H_EOK) && (prev_bufsize != 0)) { 387 ret = hv_ttrace_enable((uint64_t)TRAP_TDISABLE_ALL, 388 &prev_enable); 389 if (ret == H_EOK) { 390 if (ctlp->d.hvaddr_base == htrap_tr0) 391 htrap_tr0_inuse = 0; 392 ctlp->d.hvaddr_base = NULL; 393 ctlp->d.hlimit = 0; 394 ctlp->d.hpaddr_base = NULL; 395 } else 396 cmn_err(CE_WARN, 397 "!cpu%d: HV traptracing is not disabled, " 398 "ta: 0x%x returned error: %ld", 399 cpuid, TTRACE_ENABLE, ret); 400 } 401 } 402 } 403 404 /* 405 * This function cleans up the hypervisor traptrace buffer 406 */ 407 void 408 mach_htraptrace_cleanup(int cpuid) 409 { 410 if (mach_htraptrace_enable) { 411 TRAP_TRACE_CTL *ctlp; 412 caddr_t httrace_buf_va; 413 414 ASSERT(cpuid < max_ncpus); 415 ctlp = &trap_trace_ctl[cpuid]; 416 httrace_buf_va = ctlp->d.hvaddr_base; 417 if (httrace_buf_va == htrap_tr0) { 418 bzero(httrace_buf_va, HTRAP_TSIZE); 419 } else if (httrace_buf_va != NULL) { 420 contig_mem_free(httrace_buf_va, HTRAP_TSIZE); 421 } 422 ctlp->d.hvaddr_base = NULL; 423 ctlp->d.hlimit = 0; 424 ctlp->d.hpaddr_base = NULL; 425 } 426 } 427 428 /* 429 * Load any required machine class (sun4v) specific drivers. 430 */ 431 void 432 load_mach_drivers(void) 433 { 434 /* 435 * We don't want to load these LDOMs-specific 436 * modules if domaining is not supported. Also, 437 * we must be able to run on non-LDOMs firmware. 438 */ 439 if (!domaining_supported()) 440 return; 441 442 /* 443 * Load the core domain services module 444 */ 445 if (modload("misc", "ds") == -1) 446 cmn_err(CE_NOTE, "!'ds' module failed to load"); 447 448 /* 449 * Load the rest of the domain services 450 */ 451 if (modload("misc", "fault_iso") == -1) 452 cmn_err(CE_NOTE, "!'fault_iso' module failed to load"); 453 454 if (modload("misc", "platsvc") == -1) 455 cmn_err(CE_NOTE, "!'platsvc' module failed to load"); 456 457 if (domaining_enabled() && modload("misc", "dr_cpu") == -1) 458 cmn_err(CE_NOTE, "!'dr_cpu' module failed to load"); 459 460 /* 461 * Attempt to attach any virtual device servers. These 462 * drivers must be loaded at start of day so that they 463 * can respond to any updates to the machine description. 464 * 465 * Since it is quite likely that a domain will not support 466 * one or more of these servers, failures are ignored. 467 */ 468 469 /* virtual disk server */ 470 (void) i_ddi_attach_hw_nodes("vds"); 471 472 /* virtual network switch */ 473 (void) i_ddi_attach_hw_nodes("vsw"); 474 475 /* virtual console concentrator */ 476 (void) i_ddi_attach_hw_nodes("vcc"); 477 } 478