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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/kstat.h> 28 #include <sys/param.h> 29 #include <sys/stack.h> 30 #include <sys/regset.h> 31 #include <sys/thread.h> 32 #include <sys/proc.h> 33 #include <sys/procfs_isa.h> 34 #include <sys/kmem.h> 35 #include <sys/cpuvar.h> 36 #include <sys/systm.h> 37 #include <sys/machpcb.h> 38 #include <sys/machasi.h> 39 #include <sys/vis.h> 40 #include <sys/fpu/fpusystm.h> 41 #include <sys/cpu_module.h> 42 #include <sys/privregs.h> 43 #include <sys/archsystm.h> 44 #include <sys/atomic.h> 45 #include <sys/cmn_err.h> 46 #include <sys/time.h> 47 #include <sys/clock.h> 48 #include <sys/cmp.h> 49 #include <sys/platform_module.h> 50 #include <sys/bl.h> 51 #include <sys/nvpair.h> 52 #include <sys/kdi_impl.h> 53 #include <sys/machsystm.h> 54 #include <sys/sysmacros.h> 55 #include <sys/promif.h> 56 #include <sys/pool_pset.h> 57 #include <sys/mem.h> 58 #include <sys/dumphdr.h> 59 #include <vm/seg_kmem.h> 60 #include <sys/hold_page.h> 61 #include <sys/cpu.h> 62 63 int maxphys = MMU_PAGESIZE * 16; /* 128k */ 64 int klustsize = MMU_PAGESIZE * 16; /* 128k */ 65 66 /* 67 * Initialize kernel thread's stack. 68 */ 69 caddr_t 70 thread_stk_init(caddr_t stk) 71 { 72 kfpu_t *fp; 73 ulong_t align; 74 75 /* allocate extra space for floating point state */ 76 stk -= SA(sizeof (kfpu_t) + GSR_SIZE); 77 align = (uintptr_t)stk & 0x3f; 78 stk -= align; /* force v9_fpu to be 16 byte aligned */ 79 fp = (kfpu_t *)stk; 80 fp->fpu_fprs = 0; 81 82 stk -= SA(MINFRAME); 83 return (stk); 84 } 85 86 #define WIN32_SIZE (MAXWIN * sizeof (struct rwindow32)) 87 #define WIN64_SIZE (MAXWIN * sizeof (struct rwindow64)) 88 89 kmem_cache_t *wbuf32_cache; 90 kmem_cache_t *wbuf64_cache; 91 92 void 93 lwp_stk_cache_init(void) 94 { 95 /* 96 * Window buffers are allocated from the static arena 97 * because they are accessed at TL>0. We also must use 98 * KMC_NOHASH to prevent them from straddling page 99 * boundaries as they are accessed by physical address. 100 */ 101 wbuf32_cache = kmem_cache_create("wbuf32_cache", WIN32_SIZE, 102 0, NULL, NULL, NULL, NULL, static_arena, KMC_NOHASH); 103 wbuf64_cache = kmem_cache_create("wbuf64_cache", WIN64_SIZE, 104 0, NULL, NULL, NULL, NULL, static_arena, KMC_NOHASH); 105 } 106 107 /* 108 * Initialize lwp's kernel stack. 109 * Note that now that the floating point register save area (kfpu_t) 110 * has been broken out from machpcb and aligned on a 64 byte boundary so that 111 * we can do block load/stores to/from it, there are a couple of potential 112 * optimizations to save stack space. 1. The floating point register save 113 * area could be aligned on a 16 byte boundary, and the floating point code 114 * changed to (a) check the alignment and (b) use different save/restore 115 * macros depending upon the alignment. 2. The lwp_stk_init code below 116 * could be changed to calculate if less space would be wasted if machpcb 117 * was first instead of second. However there is a REGOFF macro used in 118 * locore, syscall_trap, machdep and mlsetup that assumes that the saved 119 * register area is a fixed distance from the %sp, and would have to be 120 * changed to a pointer or something...JJ said later. 121 */ 122 caddr_t 123 lwp_stk_init(klwp_t *lwp, caddr_t stk) 124 { 125 struct machpcb *mpcb; 126 kfpu_t *fp; 127 uintptr_t aln; 128 129 stk -= SA(sizeof (kfpu_t) + GSR_SIZE); 130 aln = (uintptr_t)stk & 0x3F; 131 stk -= aln; 132 fp = (kfpu_t *)stk; 133 stk -= SA(sizeof (struct machpcb)); 134 mpcb = (struct machpcb *)stk; 135 bzero(mpcb, sizeof (struct machpcb)); 136 bzero(fp, sizeof (kfpu_t) + GSR_SIZE); 137 lwp->lwp_regs = (void *)&mpcb->mpcb_regs; 138 lwp->lwp_fpu = (void *)fp; 139 mpcb->mpcb_fpu = fp; 140 mpcb->mpcb_fpu->fpu_q = mpcb->mpcb_fpu_q; 141 mpcb->mpcb_thread = lwp->lwp_thread; 142 mpcb->mpcb_wbcnt = 0; 143 if (lwp->lwp_procp->p_model == DATAMODEL_ILP32) { 144 mpcb->mpcb_wstate = WSTATE_USER32; 145 mpcb->mpcb_wbuf = kmem_cache_alloc(wbuf32_cache, KM_SLEEP); 146 } else { 147 mpcb->mpcb_wstate = WSTATE_USER64; 148 mpcb->mpcb_wbuf = kmem_cache_alloc(wbuf64_cache, KM_SLEEP); 149 } 150 ASSERT(((uintptr_t)mpcb->mpcb_wbuf & 7) == 0); 151 mpcb->mpcb_wbuf_pa = va_to_pa(mpcb->mpcb_wbuf); 152 mpcb->mpcb_pa = va_to_pa(mpcb); 153 return (stk); 154 } 155 156 void 157 lwp_stk_fini(klwp_t *lwp) 158 { 159 struct machpcb *mpcb = lwptompcb(lwp); 160 161 /* 162 * there might be windows still in the wbuf due to unmapped 163 * stack, misaligned stack pointer, etc. We just free it. 164 */ 165 mpcb->mpcb_wbcnt = 0; 166 if (mpcb->mpcb_wstate == WSTATE_USER32) 167 kmem_cache_free(wbuf32_cache, mpcb->mpcb_wbuf); 168 else 169 kmem_cache_free(wbuf64_cache, mpcb->mpcb_wbuf); 170 mpcb->mpcb_wbuf = NULL; 171 mpcb->mpcb_wbuf_pa = -1; 172 } 173 174 175 /* 176 * Copy regs from parent to child. 177 */ 178 void 179 lwp_forkregs(klwp_t *lwp, klwp_t *clwp) 180 { 181 kthread_t *t, *pt = lwptot(lwp); 182 struct machpcb *mpcb = lwptompcb(clwp); 183 struct machpcb *pmpcb = lwptompcb(lwp); 184 kfpu_t *fp, *pfp = lwptofpu(lwp); 185 caddr_t wbuf; 186 uint_t wstate; 187 188 t = mpcb->mpcb_thread; 189 /* 190 * remember child's fp and wbuf since they will get erased during 191 * the bcopy. 192 */ 193 fp = mpcb->mpcb_fpu; 194 wbuf = mpcb->mpcb_wbuf; 195 wstate = mpcb->mpcb_wstate; 196 /* 197 * Don't copy mpcb_frame since we hand-crafted it 198 * in thread_load(). 199 */ 200 bcopy(lwp->lwp_regs, clwp->lwp_regs, sizeof (struct machpcb) - REGOFF); 201 mpcb->mpcb_thread = t; 202 mpcb->mpcb_fpu = fp; 203 fp->fpu_q = mpcb->mpcb_fpu_q; 204 205 /* 206 * It is theoretically possibly for the lwp's wstate to 207 * be different from its value assigned in lwp_stk_init, 208 * since lwp_stk_init assumed the data model of the process. 209 * Here, we took on the data model of the cloned lwp. 210 */ 211 if (mpcb->mpcb_wstate != wstate) { 212 if (wstate == WSTATE_USER32) { 213 kmem_cache_free(wbuf32_cache, wbuf); 214 wbuf = kmem_cache_alloc(wbuf64_cache, KM_SLEEP); 215 wstate = WSTATE_USER64; 216 } else { 217 kmem_cache_free(wbuf64_cache, wbuf); 218 wbuf = kmem_cache_alloc(wbuf32_cache, KM_SLEEP); 219 wstate = WSTATE_USER32; 220 } 221 } 222 223 mpcb->mpcb_pa = va_to_pa(mpcb); 224 mpcb->mpcb_wbuf = wbuf; 225 mpcb->mpcb_wbuf_pa = va_to_pa(wbuf); 226 227 ASSERT(mpcb->mpcb_wstate == wstate); 228 229 if (mpcb->mpcb_wbcnt != 0) { 230 bcopy(pmpcb->mpcb_wbuf, mpcb->mpcb_wbuf, 231 mpcb->mpcb_wbcnt * ((mpcb->mpcb_wstate == WSTATE_USER32) ? 232 sizeof (struct rwindow32) : sizeof (struct rwindow64))); 233 } 234 235 if (pt == curthread) 236 pfp->fpu_fprs = _fp_read_fprs(); 237 if ((pfp->fpu_en) || (pfp->fpu_fprs & FPRS_FEF)) { 238 if (pt == curthread && fpu_exists) { 239 save_gsr(clwp->lwp_fpu); 240 } else { 241 uint64_t gsr; 242 gsr = get_gsr(lwp->lwp_fpu); 243 set_gsr(gsr, clwp->lwp_fpu); 244 } 245 fp_fork(lwp, clwp); 246 } 247 } 248 249 /* 250 * Free lwp fpu regs. 251 */ 252 void 253 lwp_freeregs(klwp_t *lwp, int isexec) 254 { 255 kfpu_t *fp = lwptofpu(lwp); 256 257 if (lwptot(lwp) == curthread) 258 fp->fpu_fprs = _fp_read_fprs(); 259 if ((fp->fpu_en) || (fp->fpu_fprs & FPRS_FEF)) 260 fp_free(fp, isexec); 261 } 262 263 /* 264 * These function are currently unused on sparc. 265 */ 266 /*ARGSUSED*/ 267 void 268 lwp_attach_brand_hdlrs(klwp_t *lwp) 269 {} 270 271 /*ARGSUSED*/ 272 void 273 lwp_detach_brand_hdlrs(klwp_t *lwp) 274 {} 275 276 /* 277 * fill in the extra register state area specified with the 278 * specified lwp's platform-dependent non-floating-point extra 279 * register state information 280 */ 281 /* ARGSUSED */ 282 void 283 xregs_getgfiller(klwp_id_t lwp, caddr_t xrp) 284 { 285 /* for sun4u nothing to do here, added for symmetry */ 286 } 287 288 /* 289 * fill in the extra register state area specified with the specified lwp's 290 * platform-dependent floating-point extra register state information. 291 * NOTE: 'lwp' might not correspond to 'curthread' since this is 292 * called from code in /proc to get the registers of another lwp. 293 */ 294 void 295 xregs_getfpfiller(klwp_id_t lwp, caddr_t xrp) 296 { 297 prxregset_t *xregs = (prxregset_t *)xrp; 298 kfpu_t *fp = lwptofpu(lwp); 299 uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL); 300 uint64_t gsr; 301 302 /* 303 * fp_fksave() does not flush the GSR register into 304 * the lwp area, so do it now 305 */ 306 kpreempt_disable(); 307 if (ttolwp(curthread) == lwp && fpu_exists) { 308 fp->fpu_fprs = _fp_read_fprs(); 309 if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) { 310 _fp_write_fprs(fprs); 311 fp->fpu_fprs = (V9_FPU_FPRS_TYPE)fprs; 312 } 313 save_gsr(fp); 314 } 315 gsr = get_gsr(fp); 316 kpreempt_enable(); 317 PRXREG_GSR(xregs) = gsr; 318 } 319 320 /* 321 * set the specified lwp's platform-dependent non-floating-point 322 * extra register state based on the specified input 323 */ 324 /* ARGSUSED */ 325 void 326 xregs_setgfiller(klwp_id_t lwp, caddr_t xrp) 327 { 328 /* for sun4u nothing to do here, added for symmetry */ 329 } 330 331 /* 332 * set the specified lwp's platform-dependent floating-point 333 * extra register state based on the specified input 334 */ 335 void 336 xregs_setfpfiller(klwp_id_t lwp, caddr_t xrp) 337 { 338 prxregset_t *xregs = (prxregset_t *)xrp; 339 kfpu_t *fp = lwptofpu(lwp); 340 uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL); 341 uint64_t gsr = PRXREG_GSR(xregs); 342 343 kpreempt_disable(); 344 set_gsr(gsr, lwptofpu(lwp)); 345 346 if ((lwp == ttolwp(curthread)) && fpu_exists) { 347 fp->fpu_fprs = _fp_read_fprs(); 348 if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) { 349 _fp_write_fprs(fprs); 350 fp->fpu_fprs = (V9_FPU_FPRS_TYPE)fprs; 351 } 352 restore_gsr(lwptofpu(lwp)); 353 } 354 kpreempt_enable(); 355 } 356 357 /* 358 * fill in the sun4u asrs, ie, the lwp's platform-dependent 359 * non-floating-point extra register state information 360 */ 361 /* ARGSUSED */ 362 void 363 getasrs(klwp_t *lwp, asrset_t asr) 364 { 365 /* for sun4u nothing to do here, added for symmetry */ 366 } 367 368 /* 369 * fill in the sun4u asrs, ie, the lwp's platform-dependent 370 * floating-point extra register state information 371 */ 372 void 373 getfpasrs(klwp_t *lwp, asrset_t asr) 374 { 375 kfpu_t *fp = lwptofpu(lwp); 376 uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL); 377 378 kpreempt_disable(); 379 if (ttolwp(curthread) == lwp) 380 fp->fpu_fprs = _fp_read_fprs(); 381 if ((fp->fpu_en) || (fp->fpu_fprs & FPRS_FEF)) { 382 if (fpu_exists && ttolwp(curthread) == lwp) { 383 if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) { 384 _fp_write_fprs(fprs); 385 fp->fpu_fprs = (V9_FPU_FPRS_TYPE)fprs; 386 } 387 save_gsr(fp); 388 } 389 asr[ASR_GSR] = (int64_t)get_gsr(fp); 390 } 391 kpreempt_enable(); 392 } 393 394 /* 395 * set the sun4u asrs, ie, the lwp's platform-dependent 396 * non-floating-point extra register state information 397 */ 398 /* ARGSUSED */ 399 void 400 setasrs(klwp_t *lwp, asrset_t asr) 401 { 402 /* for sun4u nothing to do here, added for symmetry */ 403 } 404 405 void 406 setfpasrs(klwp_t *lwp, asrset_t asr) 407 { 408 kfpu_t *fp = lwptofpu(lwp); 409 uint32_t fprs = (FPRS_FEF|FPRS_DU|FPRS_DL); 410 411 kpreempt_disable(); 412 if (ttolwp(curthread) == lwp) 413 fp->fpu_fprs = _fp_read_fprs(); 414 if ((fp->fpu_en) || (fp->fpu_fprs & FPRS_FEF)) { 415 set_gsr(asr[ASR_GSR], fp); 416 if (fpu_exists && ttolwp(curthread) == lwp) { 417 if ((fp->fpu_fprs & FPRS_FEF) != FPRS_FEF) { 418 _fp_write_fprs(fprs); 419 fp->fpu_fprs = (V9_FPU_FPRS_TYPE)fprs; 420 } 421 restore_gsr(fp); 422 } 423 } 424 kpreempt_enable(); 425 } 426 427 /* 428 * Create interrupt kstats for this CPU. 429 */ 430 void 431 cpu_create_intrstat(cpu_t *cp) 432 { 433 int i; 434 kstat_t *intr_ksp; 435 kstat_named_t *knp; 436 char name[KSTAT_STRLEN]; 437 zoneid_t zoneid; 438 439 ASSERT(MUTEX_HELD(&cpu_lock)); 440 441 if (pool_pset_enabled()) 442 zoneid = GLOBAL_ZONEID; 443 else 444 zoneid = ALL_ZONES; 445 446 intr_ksp = kstat_create_zone("cpu", cp->cpu_id, "intrstat", "misc", 447 KSTAT_TYPE_NAMED, PIL_MAX * 2, NULL, zoneid); 448 449 /* 450 * Initialize each PIL's named kstat 451 */ 452 if (intr_ksp != NULL) { 453 intr_ksp->ks_update = cpu_kstat_intrstat_update; 454 knp = (kstat_named_t *)intr_ksp->ks_data; 455 intr_ksp->ks_private = cp; 456 for (i = 0; i < PIL_MAX; i++) { 457 (void) snprintf(name, KSTAT_STRLEN, "level-%d-time", 458 i + 1); 459 kstat_named_init(&knp[i * 2], name, KSTAT_DATA_UINT64); 460 (void) snprintf(name, KSTAT_STRLEN, "level-%d-count", 461 i + 1); 462 kstat_named_init(&knp[(i * 2) + 1], name, 463 KSTAT_DATA_UINT64); 464 } 465 kstat_install(intr_ksp); 466 } 467 } 468 469 /* 470 * Delete interrupt kstats for this CPU. 471 */ 472 void 473 cpu_delete_intrstat(cpu_t *cp) 474 { 475 kstat_delete_byname_zone("cpu", cp->cpu_id, "intrstat", ALL_ZONES); 476 } 477 478 /* 479 * Convert interrupt statistics from CPU ticks to nanoseconds and 480 * update kstat. 481 */ 482 int 483 cpu_kstat_intrstat_update(kstat_t *ksp, int rw) 484 { 485 kstat_named_t *knp = ksp->ks_data; 486 cpu_t *cpup = (cpu_t *)ksp->ks_private; 487 int i; 488 489 if (rw == KSTAT_WRITE) 490 return (EACCES); 491 492 /* 493 * We use separate passes to copy and convert the statistics to 494 * nanoseconds. This assures that the snapshot of the data is as 495 * self-consistent as possible. 496 */ 497 498 for (i = 0; i < PIL_MAX; i++) { 499 knp[i * 2].value.ui64 = cpup->cpu_m.intrstat[i + 1][0]; 500 knp[(i * 2) + 1].value.ui64 = cpup->cpu_stats.sys.intr[i]; 501 } 502 503 for (i = 0; i < PIL_MAX; i++) { 504 knp[i * 2].value.ui64 = 505 (uint64_t)tick2ns((hrtime_t)knp[i * 2].value.ui64, 506 cpup->cpu_id); 507 } 508 509 return (0); 510 } 511 512 /* 513 * Called by common/os/cpu.c for psrinfo(1m) kstats 514 */ 515 char * 516 cpu_fru_fmri(cpu_t *cp) 517 { 518 return (cpunodes[cp->cpu_id].fru_fmri); 519 } 520 521 /* 522 * An interrupt thread is ending a time slice, so compute the interval it 523 * ran for and update the statistic for its PIL. 524 */ 525 void 526 cpu_intr_swtch_enter(kthread_id_t t) 527 { 528 uint64_t interval; 529 uint64_t start; 530 cpu_t *cpu; 531 532 ASSERT((t->t_flag & T_INTR_THREAD) != 0); 533 ASSERT(t->t_pil > 0 && t->t_pil <= LOCK_LEVEL); 534 535 /* 536 * We could be here with a zero timestamp. This could happen if: 537 * an interrupt thread which no longer has a pinned thread underneath 538 * it (i.e. it blocked at some point in its past) has finished running 539 * its handler. intr_thread() updated the interrupt statistic for its 540 * PIL and zeroed its timestamp. Since there was no pinned thread to 541 * return to, swtch() gets called and we end up here. 542 * 543 * It can also happen if an interrupt thread in intr_thread() calls 544 * preempt. It will have already taken care of updating stats. In 545 * this event, the interrupt thread will be runnable. 546 */ 547 if (t->t_intr_start) { 548 do { 549 start = t->t_intr_start; 550 interval = gettick_counter() - start; 551 } while (cas64(&t->t_intr_start, start, 0) != start); 552 cpu = CPU; 553 if (cpu->cpu_m.divisor > 1) 554 interval *= cpu->cpu_m.divisor; 555 cpu->cpu_m.intrstat[t->t_pil][0] += interval; 556 557 atomic_add_64((uint64_t *)&cpu->cpu_intracct[cpu->cpu_mstate], 558 interval); 559 } else 560 ASSERT(t->t_intr == NULL || t->t_state == TS_RUN); 561 } 562 563 564 /* 565 * An interrupt thread is returning from swtch(). Place a starting timestamp 566 * in its thread structure. 567 */ 568 void 569 cpu_intr_swtch_exit(kthread_id_t t) 570 { 571 uint64_t ts; 572 573 ASSERT((t->t_flag & T_INTR_THREAD) != 0); 574 ASSERT(t->t_pil > 0 && t->t_pil <= LOCK_LEVEL); 575 576 do { 577 ts = t->t_intr_start; 578 } while (cas64(&t->t_intr_start, ts, gettick_counter()) != ts); 579 } 580 581 582 int 583 blacklist(int cmd, const char *scheme, nvlist_t *fmri, const char *class) 584 { 585 if (&plat_blacklist) 586 return (plat_blacklist(cmd, scheme, fmri, class)); 587 588 return (ENOTSUP); 589 } 590 591 int 592 kdi_pread(caddr_t buf, size_t nbytes, uint64_t addr, size_t *ncopiedp) 593 { 594 extern void kdi_flush_caches(void); 595 size_t nread = 0; 596 uint32_t word; 597 int slop, i; 598 599 kdi_flush_caches(); 600 membar_enter(); 601 602 /* We might not begin on a word boundary. */ 603 if ((slop = addr & 3) != 0) { 604 word = ldphys(addr & ~3); 605 for (i = slop; i < 4 && nbytes > 0; i++, nbytes--, nread++) 606 *buf++ = ((uchar_t *)&word)[i]; 607 addr = roundup(addr, 4); 608 } 609 610 while (nbytes > 0) { 611 word = ldphys(addr); 612 for (i = 0; i < 4 && nbytes > 0; i++, nbytes--, nread++, addr++) 613 *buf++ = ((uchar_t *)&word)[i]; 614 } 615 616 kdi_flush_caches(); 617 618 *ncopiedp = nread; 619 return (0); 620 } 621 622 int 623 kdi_pwrite(caddr_t buf, size_t nbytes, uint64_t addr, size_t *ncopiedp) 624 { 625 extern void kdi_flush_caches(void); 626 size_t nwritten = 0; 627 uint32_t word; 628 int slop, i; 629 630 kdi_flush_caches(); 631 632 /* We might not begin on a word boundary. */ 633 if ((slop = addr & 3) != 0) { 634 word = ldphys(addr & ~3); 635 for (i = slop; i < 4 && nbytes > 0; i++, nbytes--, nwritten++) 636 ((uchar_t *)&word)[i] = *buf++; 637 stphys(addr & ~3, word); 638 addr = roundup(addr, 4); 639 } 640 641 while (nbytes > 3) { 642 for (word = 0, i = 0; i < 4; i++, nbytes--, nwritten++) 643 ((uchar_t *)&word)[i] = *buf++; 644 stphys(addr, word); 645 addr += 4; 646 } 647 648 /* We might not end with a whole word. */ 649 if (nbytes > 0) { 650 word = ldphys(addr); 651 for (i = 0; nbytes > 0; i++, nbytes--, nwritten++) 652 ((uchar_t *)&word)[i] = *buf++; 653 stphys(addr, word); 654 } 655 656 membar_enter(); 657 kdi_flush_caches(); 658 659 *ncopiedp = nwritten; 660 return (0); 661 } 662 663 static void 664 kdi_kernpanic(struct regs *regs, uint_t tt) 665 { 666 sync_reg_buf = *regs; 667 sync_tt = tt; 668 669 sync_handler(); 670 } 671 672 static void 673 kdi_plat_call(void (*platfn)(void)) 674 { 675 if (platfn != NULL) { 676 prom_suspend_prepost(); 677 platfn(); 678 prom_resume_prepost(); 679 } 680 } 681 682 void 683 mach_kdi_init(kdi_t *kdi) 684 { 685 kdi->kdi_plat_call = kdi_plat_call; 686 kdi->kdi_kmdb_enter = kmdb_enter; 687 kdi->mkdi_cpu_index = kdi_cpu_index; 688 kdi->mkdi_trap_vatotte = kdi_trap_vatotte; 689 kdi->mkdi_kernpanic = kdi_kernpanic; 690 } 691 692 693 /* 694 * get_cpu_mstate() is passed an array of timestamps, NCMSTATES 695 * long, and it fills in the array with the time spent on cpu in 696 * each of the mstates, where time is returned in nsec. 697 * 698 * No guarantee is made that the returned values in times[] will 699 * monotonically increase on sequential calls, although this will 700 * be true in the long run. Any such guarantee must be handled by 701 * the caller, if needed. This can happen if we fail to account 702 * for elapsed time due to a generation counter conflict, yet we 703 * did account for it on a prior call (see below). 704 * 705 * The complication is that the cpu in question may be updating 706 * its microstate at the same time that we are reading it. 707 * Because the microstate is only updated when the CPU's state 708 * changes, the values in cpu_intracct[] can be indefinitely out 709 * of date. To determine true current values, it is necessary to 710 * compare the current time with cpu_mstate_start, and add the 711 * difference to times[cpu_mstate]. 712 * 713 * This can be a problem if those values are changing out from 714 * under us. Because the code path in new_cpu_mstate() is 715 * performance critical, we have not added a lock to it. Instead, 716 * we have added a generation counter. Before beginning 717 * modifications, the counter is set to 0. After modifications, 718 * it is set to the old value plus one. 719 * 720 * get_cpu_mstate() will not consider the values of cpu_mstate 721 * and cpu_mstate_start to be usable unless the value of 722 * cpu_mstate_gen is both non-zero and unchanged, both before and 723 * after reading the mstate information. Note that we must 724 * protect against out-of-order loads around accesses to the 725 * generation counter. Also, this is a best effort approach in 726 * that we do not retry should the counter be found to have 727 * changed. 728 * 729 * cpu_intracct[] is used to identify time spent in each CPU 730 * mstate while handling interrupts. Such time should be reported 731 * against system time, and so is subtracted out from its 732 * corresponding cpu_acct[] time and added to 733 * cpu_acct[CMS_SYSTEM]. Additionally, intracct time is stored in 734 * %ticks, but acct time may be stored as %sticks, thus requiring 735 * different conversions before they can be compared. 736 */ 737 738 void 739 get_cpu_mstate(cpu_t *cpu, hrtime_t *times) 740 { 741 int i; 742 hrtime_t now, start; 743 uint16_t gen; 744 uint16_t state; 745 hrtime_t intracct[NCMSTATES]; 746 747 /* 748 * Load all volatile state under the protection of membar. 749 * cpu_acct[cpu_mstate] must be loaded to avoid double counting 750 * of (now - cpu_mstate_start) by a change in CPU mstate that 751 * arrives after we make our last check of cpu_mstate_gen. 752 */ 753 754 now = gethrtime_unscaled(); 755 gen = cpu->cpu_mstate_gen; 756 757 membar_consumer(); /* guarantee load ordering */ 758 start = cpu->cpu_mstate_start; 759 state = cpu->cpu_mstate; 760 for (i = 0; i < NCMSTATES; i++) { 761 intracct[i] = cpu->cpu_intracct[i]; 762 times[i] = cpu->cpu_acct[i]; 763 } 764 membar_consumer(); /* guarantee load ordering */ 765 766 if (gen != 0 && gen == cpu->cpu_mstate_gen && now > start) 767 times[state] += now - start; 768 769 for (i = 0; i < NCMSTATES; i++) { 770 scalehrtime(×[i]); 771 intracct[i] = tick2ns((hrtime_t)intracct[i], cpu->cpu_id); 772 } 773 774 for (i = 0; i < NCMSTATES; i++) { 775 if (i == CMS_SYSTEM) 776 continue; 777 times[i] -= intracct[i]; 778 if (times[i] < 0) { 779 intracct[i] += times[i]; 780 times[i] = 0; 781 } 782 times[CMS_SYSTEM] += intracct[i]; 783 } 784 } 785 786 void 787 mach_cpu_pause(volatile char *safe) 788 { 789 /* 790 * This cpu is now safe. 791 */ 792 *safe = PAUSE_WAIT; 793 membar_enter(); /* make sure stores are flushed */ 794 795 /* 796 * Now we wait. When we are allowed to continue, safe 797 * will be set to PAUSE_IDLE. 798 */ 799 while (*safe != PAUSE_IDLE) 800 SMT_PAUSE(); 801 } 802 803 /*ARGSUSED*/ 804 int 805 plat_mem_do_mmio(struct uio *uio, enum uio_rw rw) 806 { 807 return (ENOTSUP); 808 } 809 810 int 811 dump_plat_addr() 812 { 813 return (0); 814 } 815 816 void 817 dump_plat_pfn() 818 { 819 } 820 821 /* ARGSUSED */ 822 int 823 dump_plat_data(void *dump_cdata) 824 { 825 return (0); 826 } 827 828 /* ARGSUSED */ 829 int 830 plat_hold_page(pfn_t pfn, int lock, page_t **pp_ret) 831 { 832 return (PLAT_HOLD_OK); 833 } 834 835 /* ARGSUSED */ 836 void 837 plat_release_page(page_t *pp) 838 { 839 } 840 841 /* ARGSUSED */ 842 void 843 progressbar_key_abort(ldi_ident_t li) 844 { 845 } 846