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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * Copyright (c) 2011 Bayard G. Bell. All rights reserved. 26 */ 27 28 29 #include <sys/types.h> 30 #include <sys/conf.h> 31 #include <sys/ddi.h> 32 #include <sys/sunddi.h> 33 #include <sys/ddi_impldefs.h> 34 #include <sys/obpdefs.h> 35 #include <sys/cmn_err.h> 36 #include <sys/errno.h> 37 #include <sys/kmem.h> 38 #include <sys/debug.h> 39 #include <sys/sysmacros.h> 40 #include <sys/machsystm.h> 41 #include <vm/hat_sfmmu.h> 42 #include <sys/autoconf.h> 43 #include <sys/open.h> 44 #include <sys/stat.h> 45 #include <sys/modctl.h> 46 #include <sys/fhc.h> 47 #include <sys/ac.h> 48 #include <sys/cpu_module.h> 49 #include <sys/x_call.h> 50 #include <sys/fpu/fpusystm.h> 51 #include <sys/lgrp.h> 52 53 /* Useful debugging Stuff */ 54 #include <sys/nexusdebug.h> 55 56 /* 57 * Function prototypes 58 */ 59 60 static int ac_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 61 void **result); 62 static int ac_attach(dev_info_t *, ddi_attach_cmd_t); 63 static int ac_detach(dev_info_t *, ddi_detach_cmd_t); 64 static int ac_open(dev_t *, int, int, cred_t *); 65 static int ac_close(dev_t, int, int, cred_t *); 66 static int ac_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 67 68 static void ac_add_kstats(struct ac_soft_state *); 69 static void ac_del_kstats(struct ac_soft_state *); 70 static int ac_misc_kstat_update(kstat_t *, int); 71 static void ac_add_picN_kstats(dev_info_t *dip); 72 static int ac_counters_kstat_update(kstat_t *, int); 73 static void ac_get_memory_status(struct ac_soft_state *, enum ac_bank_id); 74 static void ac_eval_memory_status(struct ac_soft_state *, enum ac_bank_id); 75 static void ac_ecache_flush(uint64_t, uint64_t); 76 static int ac_pkt_init(ac_cfga_pkt_t *pkt, intptr_t arg, int flag); 77 static int ac_pkt_fini(ac_cfga_pkt_t *pkt, intptr_t arg, int flag); 78 static int ac_reset_timeout(int rw); 79 static void ac_timeout(void *); 80 static int ac_enter_transition(void); 81 static void ac_exit_transition(void); 82 83 84 int ac_add_memory(ac_cfga_pkt_t *); 85 int ac_del_memory(ac_cfga_pkt_t *); 86 int ac_mem_stat(ac_cfga_pkt_t *, int); 87 int ac_mem_test_start(ac_cfga_pkt_t *, int); 88 int ac_mem_test_stop(ac_cfga_pkt_t *, int); 89 int ac_mem_test_read(ac_cfga_pkt_t *, int); 90 int ac_mem_test_write(ac_cfga_pkt_t *, int); 91 void ac_mem_test_stop_on_close(uint_t, uint_t); 92 /* 93 * ac audit message events 94 */ 95 typedef enum { 96 AC_AUDIT_OSTATE_CONFIGURE, 97 AC_AUDIT_OSTATE_UNCONFIGURE, 98 AC_AUDIT_OSTATE_SUCCEEDED, 99 AC_AUDIT_OSTATE_CONFIGURE_FAILED, 100 AC_AUDIT_OSTATE_UNCONFIGURE_FAILED 101 } ac_audit_evt_t; 102 static void ac_policy_audit_messages(ac_audit_evt_t event, ac_cfga_pkt_t *pkt); 103 static char *ac_ostate_typestr(sysc_cfga_ostate_t ostate, ac_audit_evt_t event); 104 105 /* The memory ioctl interface version of this driver. */ 106 static ac_mem_version_t ac_mem_version = AC_MEM_ADMIN_VERSION; 107 108 static int ac_mem_exercise(ac_cfga_pkt_t *, int); 109 110 /* 111 * Configuration data structures 112 */ 113 static struct cb_ops ac_cb_ops = { 114 ac_open, /* open */ 115 ac_close, /* close */ 116 nulldev, /* strategy */ 117 nulldev, /* print */ 118 nodev, /* dump */ 119 nulldev, /* read */ 120 nulldev, /* write */ 121 ac_ioctl, /* ioctl */ 122 nodev, /* devmap */ 123 nodev, /* mmap */ 124 nodev, /* segmap */ 125 nochpoll, /* poll */ 126 ddi_prop_op, /* cb_prop_op */ 127 0, /* streamtab */ 128 D_MP | D_NEW | D_HOTPLUG, /* Driver compatibility flag */ 129 CB_REV, /* rev */ 130 nodev, /* cb_aread */ 131 nodev /* cb_awrite */ 132 }; 133 134 static struct dev_ops ac_ops = { 135 DEVO_REV, /* devo_rev, */ 136 0, /* refcnt */ 137 ac_info, /* getinfo */ 138 nulldev, /* identify */ 139 nulldev, /* probe */ 140 ac_attach, /* attach */ 141 ac_detach, /* detach */ 142 nulldev, /* reset */ 143 &ac_cb_ops, /* cb_ops */ 144 (struct bus_ops *)0, /* bus_ops */ 145 nulldev, /* power */ 146 ddi_quiesce_not_needed, /* quiesce */ 147 }; 148 149 /* 150 * Driver globals 151 */ 152 void *acp; /* ac soft state hook */ 153 static kstat_t *ac_picN_ksp[AC_NUM_PICS]; /* performance picN kstats */ 154 static int ac_attachcnt = 0; /* number of instances attached */ 155 static kmutex_t ac_attachcnt_mutex; /* ac_attachcnt lock - attach/detach */ 156 static kmutex_t ac_hot_plug_mode_mutex; 157 static timeout_id_t ac_hot_plug_timeout; 158 static int ac_hot_plug_timeout_interval = 10; 159 160 #define AC_GETSOFTC(I) \ 161 ((struct ac_soft_state *)ddi_get_soft_state(acp, (I))) 162 163 extern struct mod_ops mod_driverops; 164 165 static struct modldrv modldrv = { 166 &mod_driverops, /* Type of module. This one is a driver */ 167 "AC Leaf", /* name of module */ 168 &ac_ops, /* driver ops */ 169 }; 170 171 static struct modlinkage modlinkage = { 172 MODREV_1, 173 (void *)&modldrv, 174 NULL 175 }; 176 177 /* 178 * These are the module initialization routines. 179 */ 180 181 int 182 _init(void) 183 { 184 int error; 185 186 if ((error = ddi_soft_state_init(&acp, sizeof (struct ac_soft_state), 187 1)) != 0) 188 return (error); 189 190 if ((error = mod_install(&modlinkage)) != 0) { 191 ddi_soft_state_fini(&acp); 192 return (error); 193 } 194 /* Initialize global mutex */ 195 mutex_init(&ac_attachcnt_mutex, NULL, MUTEX_DRIVER, NULL); 196 mutex_init(&ac_hot_plug_mode_mutex, NULL, MUTEX_DRIVER, NULL); 197 return (0); 198 } 199 200 int 201 _fini(void) 202 { 203 int error; 204 205 if ((error = mod_remove(&modlinkage)) == 0) { 206 ddi_soft_state_fini(&acp); 207 mutex_destroy(&ac_attachcnt_mutex); 208 mutex_destroy(&ac_hot_plug_mode_mutex); 209 } 210 return (error); 211 } 212 213 int 214 _info(struct modinfo *modinfop) 215 { 216 return (mod_info(&modlinkage, modinfop)); 217 } 218 219 /* ARGSUSED */ 220 static int 221 ac_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 222 { 223 dev_t dev; 224 int instance; 225 226 if (infocmd == DDI_INFO_DEVT2INSTANCE) { 227 dev = (dev_t)arg; 228 instance = AC_GETINSTANCE(getminor(dev)); 229 *result = (void *)(uintptr_t)instance; 230 return (DDI_SUCCESS); 231 } 232 return (DDI_FAILURE); 233 } 234 235 static int 236 ac_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 237 { 238 int instance; 239 struct ac_soft_state *softsp; 240 struct bd_list *list = NULL; 241 242 switch (cmd) { 243 case DDI_ATTACH: 244 break; 245 246 case DDI_RESUME: 247 return (DDI_SUCCESS); 248 249 default: 250 return (DDI_FAILURE); 251 } 252 253 instance = ddi_get_instance(devi); 254 255 if (ddi_soft_state_zalloc(acp, instance) != DDI_SUCCESS) { 256 cmn_err(CE_WARN, "ddi_soft_state_zalloc failed for ac%d", 257 instance); 258 return (DDI_FAILURE); 259 } 260 261 softsp = ddi_get_soft_state(acp, instance); 262 263 /* Set the dip in the soft state */ 264 softsp->dip = devi; 265 266 /* Get the board number from this nodes parent */ 267 softsp->pdip = ddi_get_parent(softsp->dip); 268 if ((softsp->board = (int)ddi_getprop(DDI_DEV_T_ANY, softsp->pdip, 269 DDI_PROP_DONTPASS, OBP_BOARDNUM, -1)) == -1) { 270 cmn_err(CE_WARN, "ac%d: unable to retrieve %s property", 271 instance, OBP_BOARDNUM); 272 goto bad; 273 } 274 275 DPRINTF(AC_ATTACH_DEBUG, ("ac%d: devi= 0x%p\n," 276 " softsp=0x%p\n", instance, (void *)devi, (void *)softsp)); 277 278 /* map in the registers for this device. */ 279 if (ddi_map_regs(softsp->dip, 0, (caddr_t *)&softsp->ac_base, 0, 0)) { 280 cmn_err(CE_WARN, "ac%d: unable to map registers", instance); 281 goto bad; 282 } 283 284 /* Setup the pointers to the hardware registers */ 285 softsp->ac_id = (uint32_t *)softsp->ac_base; 286 softsp->ac_memctl = (uint64_t *)((char *)softsp->ac_base + 287 AC_OFF_MEMCTL); 288 softsp->ac_memdecode0 = (uint64_t *)((char *)softsp->ac_base + 289 AC_OFF_MEMDEC0); 290 softsp->ac_memdecode1 = (uint64_t *)((char *)softsp->ac_base + 291 AC_OFF_MEMDEC1); 292 softsp->ac_counter = (uint64_t *)((char *)softsp->ac_base + 293 AC_OFF_CNTR); 294 softsp->ac_mccr = (uint32_t *)((char *)softsp->ac_base + 295 AC_OFF_MCCR); 296 297 /* nothing to suspend/resume here */ 298 (void) ddi_prop_update_string(DDI_DEV_T_NONE, devi, 299 "pm-hardware-state", "no-suspend-resume"); 300 301 /* setup the the AC counter registers to allow for hotplug. */ 302 list = fhc_bdlist_lock(softsp->board); 303 304 if (list == NULL) { 305 cmn_err(CE_PANIC, "ac%d: Board %d not found in database", 306 instance, softsp->board); 307 } 308 309 /* set the AC rev into the bd list structure */ 310 list->sc.ac_compid = *softsp->ac_id; 311 312 list->ac_softsp = softsp; 313 314 if (list->sc.type == CPU_BOARD || list->sc.type == MEM_BOARD) { 315 /* Create the minor nodes */ 316 if (ddi_create_minor_node(devi, NAME_BANK0, S_IFCHR, 317 (AC_PUTINSTANCE(instance) | 0), 318 DDI_NT_ATTACHMENT_POINT, 0) == DDI_FAILURE) { 319 cmn_err(CE_WARN, "ac%d: \"%s\" " 320 "ddi_create_minor_node failed", instance, 321 NAME_BANK0); 322 } 323 if (ddi_create_minor_node(devi, NAME_BANK1, S_IFCHR, 324 (AC_PUTINSTANCE(instance) | 1), 325 DDI_NT_ATTACHMENT_POINT, 0) == DDI_FAILURE) { 326 cmn_err(CE_WARN, "ac%d: \"%s\" " 327 "ddi_create_minor_node failed", instance, 328 NAME_BANK0); 329 } 330 331 /* purge previous fhc pa database entries */ 332 fhc_del_memloc(softsp->board); 333 334 /* Inherit Memory Bank Status */ 335 ac_get_memory_status(softsp, Bank0); 336 ac_get_memory_status(softsp, Bank1); 337 /* Final Memory Bank Status evaluation and messaging */ 338 ac_eval_memory_status(softsp, Bank0); 339 ac_eval_memory_status(softsp, Bank1); 340 } 341 342 fhc_bdlist_unlock(); 343 344 /* create the kstats for this device. */ 345 ac_add_kstats(softsp); 346 347 ddi_report_dev(devi); 348 349 return (DDI_SUCCESS); 350 351 bad: 352 ddi_soft_state_free(acp, instance); 353 return (DDI_FAILURE); 354 } 355 356 /* ARGSUSED */ 357 static int 358 ac_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 359 { 360 int instance; 361 struct ac_soft_state *softsp; 362 struct bd_list *list; 363 364 /* get the instance of this devi */ 365 instance = ddi_get_instance(devi); 366 367 /* get the soft state pointer for this device node */ 368 softsp = ddi_get_soft_state(acp, instance); 369 370 switch (cmd) { 371 case DDI_SUSPEND: 372 return (DDI_SUCCESS); 373 374 case DDI_DETACH: 375 list = fhc_bdlist_lock(softsp->board); 376 377 if (fhc_bd_detachable(softsp->board)) 378 break; 379 else 380 fhc_bdlist_unlock(); 381 /* FALLTHROUGH */ 382 383 default: 384 return (DDI_FAILURE); 385 } 386 387 ASSERT(list->ac_softsp == softsp); 388 389 if (list->sc.type == CPU_BOARD || list->sc.type == MEM_BOARD) { 390 int cpui; 391 392 /* 393 * Test to see if memory is in use on a CPU/MEM board. 394 * In the case of a DR operation this condition 395 * will have been assured when the board was unconfigured. 396 */ 397 if (softsp->bank[Bank0].busy != 0 || 398 softsp->bank[Bank0].ostate == SYSC_CFGA_OSTATE_CONFIGURED || 399 softsp->bank[Bank1].busy != 0 || 400 softsp->bank[Bank1].ostate == SYSC_CFGA_OSTATE_CONFIGURED) { 401 fhc_bdlist_unlock(); 402 return (DDI_FAILURE); 403 } 404 /* 405 * CPU busy test is done by the DR sequencer before 406 * device detach called. 407 */ 408 409 /* 410 * Flush all E-caches to remove references to this 411 * board's memory. 412 * 413 * Do this one CPU at a time to avoid stalls and timeouts 414 * due to all CPUs flushing concurrently. 415 * xc_one returns silently for non-existant CPUs. 416 */ 417 for (cpui = 0; cpui < NCPU; cpui++) 418 xc_one(cpui, ac_ecache_flush, 0, 0); 419 } 420 421 list->ac_softsp = NULL; 422 423 /* delete the kstat for this driver. */ 424 ac_del_kstats(softsp); 425 426 /* unmap the registers */ 427 ddi_unmap_regs(softsp->dip, 0, (caddr_t *)&softsp->ac_base, 0, 0); 428 429 fhc_bdlist_unlock(); 430 431 /* Remove the minor nodes. */ 432 ddi_remove_minor_node(devi, NULL); 433 434 /* free the soft state structure */ 435 ddi_soft_state_free(acp, instance); 436 ddi_prop_remove_all(devi); 437 438 return (DDI_SUCCESS); 439 } 440 441 /* ARGSUSED */ 442 static int 443 ac_open(dev_t *devp, int flag, int otyp, cred_t *credp) 444 { 445 int instance; 446 dev_t dev; 447 struct ac_soft_state *softsp; 448 struct bd_list *board; 449 int vis; 450 451 dev = *devp; 452 instance = AC_GETINSTANCE(getminor(dev)); 453 softsp = AC_GETSOFTC(instance); 454 455 /* Is the instance attached? */ 456 if (softsp == NULL) { 457 #ifdef DEBUG 458 cmn_err(CE_WARN, "ac%d device not attached", instance); 459 #endif /* DEBUG */ 460 return (ENXIO); 461 } 462 463 /* 464 * If the board is not configured, hide the memory APs 465 */ 466 board = fhc_bdlist_lock(softsp->board); 467 vis = (board != NULL) && MEM_BOARD_VISIBLE(board); 468 fhc_bdlist_unlock(); 469 470 if (!vis) 471 return (ENXIO); 472 473 /* verify that otyp is appropriate */ 474 if (otyp != OTYP_CHR) { 475 return (EINVAL); 476 } 477 478 return (DDI_SUCCESS); 479 } 480 481 /* ARGSUSED */ 482 static int 483 ac_close(dev_t devt, int flag, int otyp, cred_t *credp) 484 { 485 struct ac_soft_state *softsp; 486 int instance; 487 488 instance = AC_GETINSTANCE(getminor(devt)); 489 softsp = AC_GETSOFTC(instance); 490 ASSERT(softsp != NULL); 491 ac_mem_test_stop_on_close(softsp->board, AC_GETBANK(getminor(devt))); 492 return (DDI_SUCCESS); 493 } 494 495 static int 496 ac_pkt_init(ac_cfga_pkt_t *pkt, intptr_t arg, int flag) 497 { 498 #ifdef _MULTI_DATAMODEL 499 if (ddi_model_convert_from(flag & FMODELS) == DDI_MODEL_ILP32) { 500 ac_cfga_cmd32_t ac_cmd32; 501 502 if (ddi_copyin((void *)arg, &ac_cmd32, 503 sizeof (ac_cfga_cmd32_t), flag) != 0) { 504 return (EFAULT); 505 } 506 pkt->cmd_cfga.force = ac_cmd32.force; 507 pkt->cmd_cfga.test = ac_cmd32.test; 508 pkt->cmd_cfga.arg = ac_cmd32.arg; 509 pkt->cmd_cfga.errtype = ac_cmd32.errtype; 510 pkt->cmd_cfga.outputstr = 511 (char *)(uintptr_t)ac_cmd32.outputstr; 512 pkt->cmd_cfga.private = 513 (void *)(uintptr_t)ac_cmd32.private; 514 } else 515 #endif /* _MULTI_DATAMODEL */ 516 if (ddi_copyin((void *)arg, &(pkt->cmd_cfga), 517 sizeof (ac_cfga_cmd_t), flag) != 0) { 518 return (EFAULT); 519 } 520 pkt->errbuf = kmem_zalloc(SYSC_OUTPUT_LEN, KM_SLEEP); 521 return (0); 522 } 523 524 static int 525 ac_pkt_fini(ac_cfga_pkt_t *pkt, intptr_t arg, int flag) 526 { 527 int ret = TRUE; 528 529 #ifdef _MULTI_DATAMODEL 530 if (ddi_model_convert_from(flag & FMODELS) == DDI_MODEL_ILP32) { 531 532 if (ddi_copyout(&(pkt->cmd_cfga.errtype), 533 (void *)&(((ac_cfga_cmd32_t *)arg)->errtype), 534 sizeof (ac_err_t), flag) != 0) { 535 ret = FALSE; 536 } 537 } else 538 #endif 539 if (ddi_copyout(&(pkt->cmd_cfga.errtype), 540 (void *)&(((ac_cfga_cmd_t *)arg)->errtype), 541 sizeof (ac_err_t), flag) != 0) { 542 ret = FALSE; 543 } 544 545 if ((ret != FALSE) && ((pkt->cmd_cfga.outputstr != NULL) && 546 (ddi_copyout(pkt->errbuf, pkt->cmd_cfga.outputstr, 547 SYSC_OUTPUT_LEN, flag) != 0))) { 548 ret = FALSE; 549 } 550 551 kmem_free(pkt->errbuf, SYSC_OUTPUT_LEN); 552 return (ret); 553 } 554 555 /* ARGSUSED */ 556 static int 557 ac_ioctl( 558 dev_t devt, 559 int cmd, 560 intptr_t arg, 561 int flag, 562 cred_t *cred_p, 563 int *rval_p) 564 { 565 struct ac_soft_state *softsp; 566 ac_cfga_pkt_t cfga_pkt, *pkt; 567 int instance; 568 int retval; 569 570 instance = AC_GETINSTANCE(getminor(devt)); 571 softsp = AC_GETSOFTC(instance); 572 if (softsp == NULL) { 573 #ifdef DEBUG 574 cmn_err(CE_NOTE, "ac%d device not attached", instance); 575 #endif /* DEBUG */ 576 return (ENXIO); 577 } 578 579 /* 580 * Dispose of the easy ones first. 581 */ 582 switch (cmd) { 583 case AC_MEM_ADMIN_VER: 584 /* 585 * Specify the revision of this ioctl interface driver. 586 */ 587 if (ddi_copyout(&ac_mem_version, (void *)arg, 588 sizeof (ac_mem_version_t), flag) != 0) 589 return (EFAULT); 590 return (DDI_SUCCESS); 591 592 case AC_MEM_CONFIGURE: 593 case AC_MEM_UNCONFIGURE: 594 case AC_MEM_STAT: 595 case AC_MEM_TEST_START: 596 case AC_MEM_TEST_STOP: 597 case AC_MEM_TEST_READ: 598 case AC_MEM_TEST_WRITE: 599 case AC_MEM_EXERCISE: 600 break; 601 602 default: 603 return (ENOTTY); 604 } 605 if (cmd != AC_MEM_STAT && !fpu_exists) { 606 return (ENOTSUP); 607 } 608 609 pkt = &cfga_pkt; 610 if ((retval = ac_pkt_init(pkt, arg, flag)) != 0) 611 return (retval); 612 pkt->softsp = softsp; 613 pkt->bank = AC_GETBANK(getminor(devt)); 614 615 switch (cmd) { 616 case AC_MEM_CONFIGURE: 617 if ((flag & FWRITE) == 0) { 618 retval = EBADF; 619 break; 620 } 621 622 if (pkt->cmd_cfga.private != NULL) { 623 retval = EINVAL; 624 break; 625 } 626 ac_policy_audit_messages(AC_AUDIT_OSTATE_CONFIGURE, pkt); 627 retval = ac_add_memory(pkt); 628 if (!retval) 629 ac_policy_audit_messages( 630 AC_AUDIT_OSTATE_SUCCEEDED, pkt); 631 else 632 ac_policy_audit_messages( 633 AC_AUDIT_OSTATE_CONFIGURE_FAILED, pkt); 634 break; 635 636 case AC_MEM_UNCONFIGURE: 637 if ((flag & FWRITE) == 0) { 638 retval = EBADF; 639 break; 640 } 641 642 if (pkt->cmd_cfga.private != NULL) { 643 retval = EINVAL; 644 break; 645 } 646 ac_policy_audit_messages(AC_AUDIT_OSTATE_UNCONFIGURE, pkt); 647 retval = ac_del_memory(pkt); 648 if (!retval) { 649 ac_policy_audit_messages( 650 AC_AUDIT_OSTATE_SUCCEEDED, pkt); 651 } else 652 ac_policy_audit_messages( 653 AC_AUDIT_OSTATE_UNCONFIGURE_FAILED, pkt); 654 break; 655 656 case AC_MEM_STAT: 657 /* 658 * Query usage of a bank of memory. 659 */ 660 retval = ac_mem_stat(pkt, flag); 661 break; 662 663 case AC_MEM_TEST_START: 664 if ((flag & FWRITE) == 0) { 665 retval = EBADF; 666 break; 667 } 668 669 retval = ac_mem_test_start(pkt, flag); 670 break; 671 672 case AC_MEM_TEST_STOP: 673 if ((flag & FWRITE) == 0) { 674 retval = EBADF; 675 break; 676 } 677 678 retval = ac_mem_test_stop(pkt, flag); 679 break; 680 681 case AC_MEM_TEST_READ: 682 /* 683 * read a 'page' (or less) of memory safely. 684 */ 685 if ((flag & FWRITE) == 0) { 686 retval = EBADF; 687 break; 688 } 689 690 retval = ac_mem_test_read(pkt, flag); 691 break; 692 693 case AC_MEM_TEST_WRITE: 694 /* 695 * write a 'page' (or less) of memory safely. 696 */ 697 if ((flag & FWRITE) == 0) { 698 retval = EBADF; 699 break; 700 } 701 702 retval = ac_mem_test_write(pkt, flag); 703 break; 704 705 case AC_MEM_EXERCISE: 706 retval = ac_mem_exercise(pkt, flag); 707 break; 708 709 default: 710 ASSERT(0); 711 retval = ENOTTY; 712 break; 713 } 714 715 if (ac_pkt_fini(pkt, arg, flag) != TRUE) 716 retval = EFAULT; 717 718 return (retval); 719 } 720 721 static void 722 ac_add_kstats(struct ac_soft_state *softsp) 723 { 724 struct kstat *ac_ksp, *ac_counters_ksp; 725 struct ac_kstat *ac_named_ksp; 726 struct kstat_named *ac_counters_named_data; 727 728 /* 729 * create the unix-misc kstat for address controller 730 * using the board number as the instance. 731 */ 732 if ((ac_ksp = kstat_create("unix", softsp->board, 733 AC_KSTAT_NAME, "misc", KSTAT_TYPE_NAMED, 734 sizeof (struct ac_kstat) / sizeof (kstat_named_t), 735 KSTAT_FLAG_PERSISTENT)) == NULL) { 736 cmn_err(CE_WARN, "ac%d: kstat_create failed", 737 ddi_get_instance(softsp->dip)); 738 return; 739 } 740 741 ac_named_ksp = (struct ac_kstat *)(ac_ksp->ks_data); 742 743 /* initialize the named kstats */ 744 kstat_named_init(&ac_named_ksp->ac_memctl, 745 MEMCTL_KSTAT_NAMED, 746 KSTAT_DATA_UINT64); 747 748 kstat_named_init(&ac_named_ksp->ac_memdecode0, 749 MEMDECODE0_KSTAT_NAMED, 750 KSTAT_DATA_UINT64); 751 752 kstat_named_init(&ac_named_ksp->ac_memdecode1, 753 MEMDECODE1_KSTAT_NAMED, 754 KSTAT_DATA_UINT64); 755 756 kstat_named_init(&ac_named_ksp->ac_mccr, 757 MCCR_KSTAT_NAMED, 758 KSTAT_DATA_UINT32); 759 760 kstat_named_init(&ac_named_ksp->ac_counter, 761 CNTR_KSTAT_NAMED, 762 KSTAT_DATA_UINT64); 763 764 kstat_named_init(&ac_named_ksp->ac_bank0_status, 765 BANK_0_KSTAT_NAMED, 766 KSTAT_DATA_CHAR); 767 768 kstat_named_init(&ac_named_ksp->ac_bank1_status, 769 BANK_1_KSTAT_NAMED, 770 KSTAT_DATA_CHAR); 771 772 ac_ksp->ks_update = ac_misc_kstat_update; 773 ac_ksp->ks_private = (void *)softsp; 774 softsp->ac_ksp = ac_ksp; 775 kstat_install(ac_ksp); 776 777 /* 778 * Create the picN kstats if we are the first instance 779 * to attach. We use ac_attachcnt as a count of how 780 * many instances have attached. This is protected by 781 * a mutex. 782 */ 783 mutex_enter(&ac_attachcnt_mutex); 784 if (ac_attachcnt == 0) 785 ac_add_picN_kstats(softsp->dip); 786 787 ac_attachcnt ++; 788 mutex_exit(&ac_attachcnt_mutex); 789 790 /* 791 * Create the "counter" kstat for each AC instance. 792 * This provides access to the %pcr and %pic 793 * registers for that instance. 794 * 795 * The size of this kstat is AC_NUM_PICS + 1 for %pcr 796 */ 797 if ((ac_counters_ksp = kstat_create("ac", 798 ddi_get_instance(softsp->dip), "counters", 799 "bus", KSTAT_TYPE_NAMED, AC_NUM_PICS + 1, 800 KSTAT_FLAG_WRITABLE)) == NULL) { 801 802 cmn_err(CE_WARN, "ac%d counters: kstat_create failed", 803 ddi_get_instance(softsp->dip)); 804 return; 805 } 806 ac_counters_named_data = 807 (struct kstat_named *)(ac_counters_ksp->ks_data); 808 809 /* initialize the named kstats */ 810 kstat_named_init(&ac_counters_named_data[0], 811 "pcr", KSTAT_DATA_UINT64); 812 813 kstat_named_init(&ac_counters_named_data[1], 814 "pic0", KSTAT_DATA_UINT64); 815 816 kstat_named_init(&ac_counters_named_data[2], 817 "pic1", KSTAT_DATA_UINT64); 818 819 ac_counters_ksp->ks_update = ac_counters_kstat_update; 820 ac_counters_ksp->ks_private = (void *)softsp; 821 kstat_install(ac_counters_ksp); 822 823 /* update the sofstate */ 824 softsp->ac_counters_ksp = ac_counters_ksp; 825 } 826 827 /* 828 * called from ac_add_kstats() to create a kstat for each %pic 829 * that the AC supports. These (read-only) kstats export the 830 * event names and %pcr masks that each %pic supports. 831 * 832 * if we fail to create any of these kstats we must remove any 833 * that we have already created and return; 834 * 835 * NOTE: because all AC's use the same events we only need to 836 * create the picN kstats once. All instances can use 837 * the same picN kstats. 838 * 839 * The flexibility exists to allow each device specify it's 840 * own events by creating picN kstats with the instance number 841 * set to ddi_get_instance(softsp->dip). 842 * 843 * When searching for a picN kstat for a device you should 844 * first search for a picN kstat using the instance number 845 * of the device you are interested in. If that fails you 846 * should use the first picN kstat found for that device. 847 */ 848 static void 849 ac_add_picN_kstats(dev_info_t *dip) 850 { 851 typedef struct ac_event_mask { 852 char *event_name; 853 uint64_t pcr_mask; 854 } ac_event_mask_t; 855 856 /* 857 * AC Performance Events. 858 * 859 * We declare an array of event-names and event-masks. 860 */ 861 ac_event_mask_t ac_events_arr[] = { 862 {"mem_bank0_rds", 0x1}, {"mem_bank0_wrs", 0x2}, 863 {"mem_bank0_stall", 0x3}, {"mem_bank1_rds", 0x4}, 864 {"mem_bank1_wrs", 0x5}, {"mem_bank1_stall", 0x6}, 865 {"clock_cycles", 0x7}, {"addr_pkts", 0x8}, 866 {"data_pkts", 0x9}, {"flow_ctl_cyc", 0xa}, 867 {"fast_arb_pkts", 0xb}, {"bus_cont_cyc", 0xc}, 868 {"data_bus_can", 0xd}, {"ac_addr_pkts", 0xe}, 869 {"ac_data_pkts", 0xf}, {"rts_pkts", 0x10}, 870 {"rtsa_pkts", 0x11}, {"rto_pkts", 0x12}, 871 {"rs_pkts", 0x13}, {"wb_pkts", 0x14}, 872 {"ws_pkts", 0x15}, {"rio_pkts", 0x16}, 873 {"rbio_pkts", 0x17}, {"wio_pkts", 0x18}, 874 {"wbio_pkts", 0x19}, {"upa_a_rds_m", 0x1a}, 875 {"upa_a_rdo_v", 0x1b}, {"upa_b_rds_m", 0x1c}, 876 {"upa_b_rdo_v", 0x1d}, {"upa_a_preqs_fr", 0x20}, 877 {"upa_a_sreqs_to", 0x21}, {"upa_a_preqs_to", 0x22}, 878 {"upa_a_rds_fr", 0x23}, {"upa_a_rdsa_fr", 0x24}, 879 {"upa_a_rdo_fr", 0x25}, {"upa_a_rdd_fr", 0x26}, 880 {"upa_a_rio_rbio", 0x27}, {"upa_a_wio_wbio", 0x28}, 881 {"upa_a_cpb_to", 0x29}, {"upa_a_inv_to", 0x2a}, 882 {"upa_a_hits_buff", 0x2b}, {"upa_a_wb", 0x2c}, 883 {"upa_a_wi", 0x2d}, {"upa_b_preqs_fr", 0x30}, 884 {"upa_b_sreqs_to", 0x31}, {"upa_b_preqs_to", 0x32}, 885 {"upa_b_rds_fr", 0x33}, {"upa_b_rdsa_fr", 0x34}, 886 {"upa_b_rdo_fr", 0x35}, {"upa_b_rdd_fr", 0x36}, 887 {"upa_b_rio_rbio", 0x37}, {"upa_b_wio_wbio", 0x38}, 888 {"upa_b_cpb_to", 0x39}, {"upa_b_inv_to", 0x3a}, 889 {"upa_b_hits_buff", 0x3b}, {"upa_b_wb", 0x3c}, 890 {"upa_b_wi", 0x3d} 891 }; 892 893 #define AC_NUM_EVENTS sizeof (ac_events_arr) / sizeof (ac_events_arr[0]) 894 895 /* 896 * array of clear masks for each pic. 897 * These masks are used to clear the %pcr bits for 898 * each pic. 899 */ 900 ac_event_mask_t ac_clear_pic[AC_NUM_PICS] = { 901 /* pic0 */ 902 {"clear_pic", (uint64_t)~(0x3f)}, 903 /* pic1 */ 904 {"clear_pic", (uint64_t)~(0x3f << 8)} 905 }; 906 907 struct kstat_named *ac_pic_named_data; 908 int event, pic; 909 char pic_name[30]; 910 int instance = ddi_get_instance(dip); 911 int pic_shift = 0; 912 913 for (pic = 0; pic < AC_NUM_PICS; pic++) { 914 /* 915 * create the picN kstat. The size of this kstat is 916 * AC_NUM_EVENTS + 1 for the clear_event_mask 917 */ 918 (void) sprintf(pic_name, "pic%d", pic); /* pic0, pic1 ... */ 919 if ((ac_picN_ksp[pic] = kstat_create("ac", 920 instance, pic_name, "bus", KSTAT_TYPE_NAMED, 921 AC_NUM_EVENTS + 1, 0)) == NULL) { 922 923 cmn_err(CE_WARN, "ac %s: kstat_create failed", 924 pic_name); 925 926 /* remove pic0 kstat if pic1 create fails */ 927 if (pic == 1) { 928 kstat_delete(ac_picN_ksp[0]); 929 ac_picN_ksp[0] = NULL; 930 } 931 return; 932 } 933 ac_pic_named_data = 934 (struct kstat_named *)(ac_picN_ksp[pic]->ks_data); 935 936 /* 937 * when we are storing pcr_masks we need to shift bits 938 * left by 8 for pic1 events. 939 */ 940 if (pic == 1) 941 pic_shift = 8; 942 943 /* 944 * for each picN event we need to write a kstat record 945 * (name = EVENT, value.ui64 = PCR_MASK) 946 */ 947 for (event = 0; event < AC_NUM_EVENTS; event ++) { 948 949 /* pcr_mask */ 950 ac_pic_named_data[event].value.ui64 = 951 ac_events_arr[event].pcr_mask << pic_shift; 952 953 /* event-name */ 954 kstat_named_init(&ac_pic_named_data[event], 955 ac_events_arr[event].event_name, 956 KSTAT_DATA_UINT64); 957 } 958 959 /* 960 * we add the clear_pic event and mask as the last 961 * record in the kstat 962 */ 963 /* pcr mask */ 964 ac_pic_named_data[AC_NUM_EVENTS].value.ui64 = 965 ac_clear_pic[pic].pcr_mask; 966 967 /* event-name */ 968 kstat_named_init(&ac_pic_named_data[AC_NUM_EVENTS], 969 ac_clear_pic[pic].event_name, 970 KSTAT_DATA_UINT64); 971 972 kstat_install(ac_picN_ksp[pic]); 973 } 974 } 975 976 977 static void 978 ac_del_kstats(struct ac_soft_state *softsp) 979 { 980 struct kstat *ac_ksp; 981 int pic; 982 983 /* remove "misc" kstat */ 984 ac_ksp = softsp->ac_ksp; 985 softsp->ac_ksp = NULL; 986 if (ac_ksp != NULL) { 987 ASSERT(ac_ksp->ks_private == (void *)softsp); 988 kstat_delete(ac_ksp); 989 } 990 991 /* remove "bus" kstat */ 992 ac_ksp = softsp->ac_counters_ksp; 993 softsp->ac_counters_ksp = NULL; 994 if (ac_ksp != NULL) { 995 ASSERT(ac_ksp->ks_private == (void *)softsp); 996 kstat_delete(ac_ksp); 997 } 998 999 /* 1000 * if we are the last instance to detach we need to 1001 * remove the picN kstats. We use ac_attachcnt as a 1002 * count of how many instances are still attached. This 1003 * is protected by a mutex. 1004 */ 1005 mutex_enter(&ac_attachcnt_mutex); 1006 ac_attachcnt --; 1007 if (ac_attachcnt == 0) { 1008 for (pic = 0; pic < AC_NUM_PICS; pic++) { 1009 if (ac_picN_ksp[pic] != (kstat_t *)NULL) { 1010 kstat_delete(ac_picN_ksp[pic]); 1011 ac_picN_ksp[pic] = NULL; 1012 } 1013 } 1014 } 1015 mutex_exit(&ac_attachcnt_mutex); 1016 } 1017 1018 static enum ac_bank_status 1019 ac_kstat_stat(sysc_cfga_rstate_t rst, sysc_cfga_ostate_t ost) 1020 { 1021 switch (rst) { 1022 case SYSC_CFGA_RSTATE_EMPTY: 1023 return (StNoMem); 1024 case SYSC_CFGA_RSTATE_DISCONNECTED: 1025 return (StBad); 1026 case SYSC_CFGA_RSTATE_CONNECTED: 1027 switch (ost) { 1028 case SYSC_CFGA_OSTATE_UNCONFIGURED: 1029 return (StSpare); 1030 case SYSC_CFGA_OSTATE_CONFIGURED: 1031 return (StActive); 1032 default: 1033 return (StUnknown); 1034 } 1035 default: 1036 return (StUnknown); 1037 } 1038 } 1039 1040 static enum ac_bank_condition 1041 ac_kstat_cond(sysc_cfga_cond_t cond) 1042 { 1043 switch (cond) { 1044 case SYSC_CFGA_COND_UNKNOWN: 1045 return (ConUnknown); 1046 case SYSC_CFGA_COND_OK: 1047 return (ConOK); 1048 case SYSC_CFGA_COND_FAILING: 1049 return (ConFailing); 1050 case SYSC_CFGA_COND_FAILED: 1051 return (ConFailed); 1052 case SYSC_CFGA_COND_UNUSABLE: 1053 return (ConBad); 1054 default: 1055 return (ConUnknown); 1056 } 1057 } 1058 1059 static int 1060 ac_misc_kstat_update(kstat_t *ksp, int rw) 1061 { 1062 struct ac_kstat *acksp; 1063 struct ac_soft_state *softsp; 1064 1065 acksp = (struct ac_kstat *)ksp->ks_data; 1066 softsp = (struct ac_soft_state *)ksp->ks_private; 1067 /* Need the NULL check in case kstat is about to be deleted. */ 1068 ASSERT(softsp->ac_ksp == NULL || ksp == softsp->ac_ksp); 1069 1070 /* this is a read-only kstat. Bail out on a write */ 1071 if (rw == KSTAT_WRITE) { 1072 return (EACCES); 1073 } else { 1074 /* 1075 * copy the current state of the hardware into the 1076 * kstat structure. 1077 */ 1078 acksp->ac_memctl.value.ui64 = *softsp->ac_memctl; 1079 acksp->ac_memdecode0.value.ui64 = *softsp->ac_memdecode0; 1080 acksp->ac_memdecode1.value.ui64 = *softsp->ac_memdecode1; 1081 acksp->ac_mccr.value.ui32 = *softsp->ac_mccr; 1082 acksp->ac_counter.value.ui64 = *softsp->ac_counter; 1083 acksp->ac_bank0_status.value.c[0] = 1084 ac_kstat_stat(softsp->bank[0].rstate, 1085 softsp->bank[0].ostate); 1086 acksp->ac_bank0_status.value.c[1] = 1087 ac_kstat_cond(softsp->bank[0].condition); 1088 acksp->ac_bank1_status.value.c[0] = 1089 ac_kstat_stat(softsp->bank[1].rstate, 1090 softsp->bank[1].ostate); 1091 acksp->ac_bank1_status.value.c[1] = 1092 ac_kstat_cond(softsp->bank[1].condition); 1093 } 1094 return (0); 1095 } 1096 1097 static int 1098 ac_counters_kstat_update(kstat_t *ksp, int rw) 1099 { 1100 struct kstat_named *ac_counters_data; 1101 struct ac_soft_state *softsp; 1102 uint64_t pic_register; 1103 1104 ac_counters_data = (struct kstat_named *)ksp->ks_data; 1105 softsp = (struct ac_soft_state *)ksp->ks_private; 1106 1107 /* 1108 * We need to start/restart the ac_timeout that will 1109 * return the AC counters to hot-plug mode after the 1110 * ac_hot_plug_timeout_interval has expired. We tell 1111 * ac_reset_timeout() whether this is a kstat_read or a 1112 * kstat_write call. If this fails we reject the kstat 1113 * operation. 1114 */ 1115 if (ac_reset_timeout(rw) != 0) 1116 return (-1); 1117 1118 1119 if (rw == KSTAT_WRITE) { 1120 /* 1121 * Write the %pcr value to the softsp->ac_mccr. 1122 * This interface does not support writing to the 1123 * %pic. 1124 */ 1125 *softsp->ac_mccr = 1126 (uint32_t)ac_counters_data[0].value.ui64; 1127 } else { 1128 /* 1129 * Read %pcr and %pic register values and write them 1130 * into counters kstat. 1131 */ 1132 1133 /* pcr */ 1134 ac_counters_data[0].value.ui64 = *softsp->ac_mccr; 1135 1136 pic_register = *softsp->ac_counter; 1137 /* 1138 * ac pic register: 1139 * (63:32) = pic1 1140 * (31:00) = pic0 1141 */ 1142 1143 /* pic0 */ 1144 ac_counters_data[1].value.ui64 = 1145 AC_COUNTER_TO_PIC0(pic_register); 1146 /* pic1 */ 1147 ac_counters_data[2].value.ui64 = 1148 AC_COUNTER_TO_PIC1(pic_register); 1149 } 1150 return (0); 1151 } 1152 1153 /* 1154 * Decode the memory state given to us and plug it into the soft state 1155 */ 1156 static void 1157 ac_get_memory_status(struct ac_soft_state *softsp, enum ac_bank_id id) 1158 { 1159 char *property = (id == Bank0) ? AC_BANK0_STATUS : AC_BANK1_STATUS; 1160 char *propval; 1161 int proplen; 1162 uint64_t memdec = (id == Bank0) ? 1163 *(softsp->ac_memdecode0) : *(softsp->ac_memdecode1); 1164 uint_t grp_size; 1165 1166 softsp->bank[id].busy = 0; 1167 softsp->bank[id].status_change = ddi_get_time(); 1168 1169 if (GRP_SIZE_IS_SET(memdec)) { 1170 grp_size = GRP_SPANMB(memdec); 1171 1172 /* determine the memory bank size (in MB) */ 1173 softsp->bank[id].real_size = softsp->bank[id].use_size = 1174 (id == Bank0) ? (grp_size / INTLV0(*softsp->ac_memctl)) : 1175 (grp_size / INTLV1(*softsp->ac_memctl)); 1176 } else { 1177 softsp->bank[id].real_size = softsp->bank[id].use_size = 0; 1178 } 1179 1180 /* 1181 * decode the memory bank property. set condition based 1182 * on the values. 1183 */ 1184 if (ddi_prop_op(DDI_DEV_T_ANY, softsp->dip, PROP_LEN_AND_VAL_ALLOC, 1185 DDI_PROP_DONTPASS, property, (caddr_t)&propval, &proplen) == 1186 DDI_PROP_SUCCESS) { 1187 if (strcmp(propval, AC_BANK_NOMEM) == 0) { 1188 softsp->bank[id].rstate = SYSC_CFGA_RSTATE_EMPTY; 1189 softsp->bank[id].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 1190 softsp->bank[id].condition = SYSC_CFGA_COND_UNKNOWN; 1191 } else if (strcmp(propval, AC_BANK_OK) == 0) { 1192 softsp->bank[id].rstate = SYSC_CFGA_RSTATE_CONNECTED; 1193 softsp->bank[id].ostate = SYSC_CFGA_OSTATE_CONFIGURED; 1194 softsp->bank[id].condition = SYSC_CFGA_COND_OK; 1195 } else if (strcmp(propval, AC_BANK_SPARE) == 0) { 1196 softsp->bank[id].rstate = SYSC_CFGA_RSTATE_CONNECTED; 1197 softsp->bank[id].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 1198 softsp->bank[id].condition = SYSC_CFGA_COND_UNKNOWN; 1199 } else if (strcmp(propval, AC_BANK_FAILED) == 0) { 1200 softsp->bank[id].rstate = SYSC_CFGA_RSTATE_DISCONNECTED; 1201 softsp->bank[id].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 1202 softsp->bank[id].condition = SYSC_CFGA_COND_UNUSABLE; 1203 } else { 1204 cmn_err(CE_WARN, "ac%d: board %d, bank %d: " 1205 "unknown %smemory state [%s]", 1206 ddi_get_instance(softsp->dip), softsp->board, id, 1207 (memdec & AC_MEM_VALID) ? "connected " : "", 1208 propval); 1209 if (memdec & AC_MEM_VALID) { 1210 softsp->bank[id].rstate = 1211 SYSC_CFGA_RSTATE_CONNECTED; 1212 softsp->bank[id].ostate = 1213 SYSC_CFGA_OSTATE_CONFIGURED; 1214 softsp->bank[id].condition = 1215 SYSC_CFGA_COND_OK; 1216 } else { 1217 softsp->bank[id].rstate = 1218 SYSC_CFGA_RSTATE_DISCONNECTED; 1219 softsp->bank[id].ostate = 1220 SYSC_CFGA_OSTATE_UNCONFIGURED; 1221 softsp->bank[id].condition = 1222 SYSC_CFGA_COND_UNUSABLE; 1223 } 1224 } 1225 1226 kmem_free(propval, proplen); 1227 } else { 1228 /* we don't have the property, deduce the state of memory */ 1229 if (memdec & AC_MEM_VALID) { 1230 softsp->bank[id].rstate = SYSC_CFGA_RSTATE_CONNECTED; 1231 softsp->bank[id].ostate = SYSC_CFGA_OSTATE_CONFIGURED; 1232 softsp->bank[id].condition = SYSC_CFGA_COND_OK; 1233 } else { 1234 /* could be an i/o board... */ 1235 softsp->bank[id].rstate = SYSC_CFGA_RSTATE_EMPTY; 1236 softsp->bank[id].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 1237 softsp->bank[id].condition = SYSC_CFGA_COND_UNKNOWN; 1238 } 1239 } 1240 1241 /* we assume that all other bank statuses are NOT valid */ 1242 if (softsp->bank[id].rstate == SYSC_CFGA_RSTATE_CONNECTED) { 1243 if ((memdec & AC_MEM_VALID) != 0) { 1244 uint64_t base_pa; 1245 1246 ASSERT((*softsp->ac_memctl & AC_CSR_REFEN) != 0); 1247 /* register existence in the memloc database */ 1248 base_pa = GRP_REALBASE(memdec); 1249 fhc_add_memloc(softsp->board, base_pa, grp_size); 1250 } 1251 } 1252 } 1253 1254 static void 1255 ac_eval_memory_status(struct ac_soft_state *softsp, enum ac_bank_id id) 1256 { 1257 uint64_t memdec = (id == Bank0) ? 1258 *(softsp->ac_memdecode0) : *(softsp->ac_memdecode1); 1259 uint64_t base_pa; 1260 1261 /* 1262 * Downgrade the status of any bank that did not get 1263 * programmed. 1264 */ 1265 if (softsp->bank[id].rstate == SYSC_CFGA_RSTATE_CONNECTED && 1266 softsp->bank[id].ostate == SYSC_CFGA_OSTATE_UNCONFIGURED && 1267 (memdec & AC_MEM_VALID) == 0) { 1268 cmn_err(CE_WARN, "ac%d: board %d, bank %d: " 1269 "spare memory bank not valid - it was ", 1270 ddi_get_instance(softsp->dip), softsp->board, id); 1271 cmn_err(CE_WARN, "misconfigured by the system " 1272 "firmware. Disabling..."); 1273 softsp->bank[id].rstate = SYSC_CFGA_RSTATE_DISCONNECTED; 1274 softsp->bank[id].ostate = SYSC_CFGA_OSTATE_UNCONFIGURED; 1275 softsp->bank[id].condition = SYSC_CFGA_COND_UNUSABLE; 1276 } 1277 /* 1278 * Log a message about good banks. 1279 */ 1280 if (softsp->bank[id].rstate == SYSC_CFGA_RSTATE_CONNECTED) { 1281 ASSERT((memdec & AC_MEM_VALID) != 0); 1282 base_pa = GRP_REALBASE(memdec); 1283 1284 cmn_err(CE_CONT, "?ac%d board %d bank %d: " 1285 "base 0x%" PRIx64 " size %dmb rstate %d " 1286 "ostate %d condition %d\n", 1287 ddi_get_instance(softsp->dip), 1288 softsp->board, id, base_pa, softsp->bank[id].real_size, 1289 softsp->bank[id].rstate, softsp->bank[id].ostate, 1290 softsp->bank[id].condition); 1291 } 1292 } 1293 1294 /*ARGSUSED*/ 1295 static void 1296 ac_ecache_flush(uint64_t a, uint64_t b) 1297 { 1298 cpu_flush_ecache(); 1299 } 1300 1301 static char * 1302 ac_ostate_typestr(sysc_cfga_ostate_t ostate, ac_audit_evt_t event) 1303 { 1304 char *type_str; 1305 1306 switch (ostate) { 1307 case SYSC_CFGA_OSTATE_UNCONFIGURED: 1308 switch (event) { 1309 case AC_AUDIT_OSTATE_UNCONFIGURE: 1310 type_str = "unconfiguring"; 1311 break; 1312 case AC_AUDIT_OSTATE_SUCCEEDED: 1313 case AC_AUDIT_OSTATE_UNCONFIGURE_FAILED: 1314 type_str = "unconfigured"; 1315 break; 1316 default: 1317 type_str = "unconfigure?"; 1318 break; 1319 } 1320 break; 1321 case SYSC_CFGA_OSTATE_CONFIGURED: 1322 switch (event) { 1323 case AC_AUDIT_OSTATE_CONFIGURE: 1324 type_str = "configuring"; 1325 break; 1326 case AC_AUDIT_OSTATE_SUCCEEDED: 1327 case AC_AUDIT_OSTATE_CONFIGURE_FAILED: 1328 type_str = "configured"; 1329 break; 1330 default: 1331 type_str = "configure?"; 1332 break; 1333 } 1334 break; 1335 1336 default: 1337 type_str = "undefined occupant state"; 1338 break; 1339 } 1340 return (type_str); 1341 } 1342 1343 static void 1344 ac_policy_audit_messages(ac_audit_evt_t event, ac_cfga_pkt_t *pkt) 1345 { 1346 struct ac_soft_state *softsp = pkt->softsp; 1347 1348 switch (event) { 1349 case AC_AUDIT_OSTATE_CONFIGURE: 1350 cmn_err(CE_NOTE, 1351 "%s memory bank %d in slot %d", 1352 ac_ostate_typestr(SYSC_CFGA_OSTATE_CONFIGURED, 1353 event), pkt->bank, 1354 softsp->board); 1355 break; 1356 case AC_AUDIT_OSTATE_UNCONFIGURE: 1357 cmn_err(CE_NOTE, 1358 "%s memory bank %d in slot %d", 1359 ac_ostate_typestr( 1360 SYSC_CFGA_OSTATE_UNCONFIGURED, 1361 event), pkt->bank, 1362 softsp->board); 1363 break; 1364 case AC_AUDIT_OSTATE_SUCCEEDED: 1365 cmn_err(CE_NOTE, 1366 "memory bank %d in slot %d is %s", 1367 pkt->bank, softsp->board, 1368 ac_ostate_typestr( 1369 softsp->bank[pkt->bank].ostate, 1370 event)); 1371 break; 1372 case AC_AUDIT_OSTATE_CONFIGURE_FAILED: 1373 cmn_err(CE_NOTE, 1374 "memory bank %d in slot %d not %s", 1375 pkt->bank, 1376 softsp->board, 1377 ac_ostate_typestr( 1378 SYSC_CFGA_OSTATE_CONFIGURED, 1379 event)); 1380 break; 1381 case AC_AUDIT_OSTATE_UNCONFIGURE_FAILED: 1382 cmn_err(CE_NOTE, 1383 "memory bank %d in slot %d not %s", 1384 pkt->bank, 1385 softsp->board, 1386 ac_ostate_typestr( 1387 SYSC_CFGA_OSTATE_UNCONFIGURED, 1388 event)); 1389 break; 1390 default: 1391 cmn_err(CE_NOTE, 1392 "unknown audit of memory bank %d in slot %d", 1393 pkt->bank, softsp->board); 1394 break; 1395 } 1396 } 1397 1398 #include <vm/page.h> 1399 #include <vm/hat.h> 1400 1401 static int 1402 ac_mem_exercise(ac_cfga_pkt_t *pkt, int flag) 1403 { 1404 struct ac_mem_info *mem_info; 1405 pfn_t base; 1406 pgcnt_t npgs; 1407 1408 mem_info = &pkt->softsp->bank[pkt->bank]; 1409 if (mem_info->rstate == SYSC_CFGA_RSTATE_CONNECTED) { 1410 uint64_t base_pa, bank_size; 1411 uint64_t decode; 1412 1413 decode = (pkt->bank == Bank0) ? 1414 *pkt->softsp->ac_memdecode0 : *pkt->softsp->ac_memdecode1; 1415 base_pa = GRP_REALBASE(decode); 1416 bank_size = GRP_UK2SPAN(decode); 1417 1418 base = base_pa >> PAGESHIFT; 1419 npgs = bank_size >> PAGESHIFT; 1420 } else { 1421 base = 0; 1422 npgs = 0; 1423 } 1424 switch (pkt->cmd_cfga.arg) { 1425 case AC_MEMX_RELOCATE_ALL: { 1426 pfn_t pfn, pglim; 1427 struct ac_memx_relocate_stats rstat; 1428 1429 if (npgs == 0 || 1430 mem_info->ostate != SYSC_CFGA_OSTATE_CONFIGURED) { 1431 return (EINVAL); 1432 } 1433 if (mem_info->busy != FALSE) { 1434 return (EBUSY); 1435 } 1436 bzero(&rstat, sizeof (rstat)); 1437 rstat.base = (uint_t)base; 1438 rstat.npgs = (uint_t)npgs; 1439 pglim = base + npgs; 1440 for (pfn = base; pfn < pglim; pfn++) { 1441 page_t *pp, *pp_repl; 1442 1443 retry: 1444 pp = page_numtopp_nolock(pfn); 1445 if (pp != NULL) { 1446 if (!page_trylock(pp, SE_EXCL)) { 1447 pp = NULL; 1448 rstat.nolock++; 1449 } 1450 if (pp != NULL && page_pptonum(pp) != pfn) { 1451 page_unlock(pp); 1452 goto retry; 1453 } 1454 } else { 1455 rstat.nopaget++; 1456 } 1457 if (pp != NULL && PP_ISFREE(pp)) { 1458 page_unlock(pp); 1459 rstat.isfree++; 1460 pp = NULL; 1461 } 1462 if (pp != NULL) { 1463 spgcnt_t npgs; 1464 int result; 1465 1466 pp_repl = NULL; 1467 result = page_relocate(&pp, &pp_repl, 1, 1, 1468 &npgs, NULL); 1469 if (result == 0) { 1470 while (npgs-- > 0) { 1471 page_t *tpp; 1472 1473 ASSERT(pp_repl != NULL); 1474 tpp = pp_repl; 1475 page_sub(&pp_repl, tpp); 1476 page_unlock(tpp); 1477 } 1478 1479 rstat.reloc++; 1480 } else { 1481 page_unlock(pp); 1482 rstat.noreloc++; 1483 } 1484 } 1485 } 1486 if (pkt->cmd_cfga.private != NULL && ddi_copyout(&rstat, 1487 pkt->cmd_cfga.private, sizeof (rstat), flag) != 0) 1488 return (EFAULT); 1489 return (DDI_SUCCESS); 1490 } 1491 1492 default: 1493 return (EINVAL); 1494 } 1495 } 1496 1497 static int 1498 ac_reset_timeout(int rw) 1499 { 1500 mutex_enter(&ac_hot_plug_mode_mutex); 1501 1502 if ((ac_hot_plug_timeout == (timeout_id_t)NULL) && 1503 (rw == KSTAT_READ)) { 1504 /* 1505 * We are in hot-plug mode. A kstat_read is not 1506 * going to affect this. return 0 to allow the 1507 * kstat_read to continue. 1508 */ 1509 mutex_exit(&ac_hot_plug_mode_mutex); 1510 return (0); 1511 1512 } else if ((ac_hot_plug_timeout == (timeout_id_t)NULL) && 1513 (rw == KSTAT_WRITE)) { 1514 /* 1515 * There are no pending timeouts and we have received a 1516 * kstat_write request so we must be transitioning 1517 * from "hot-plug" mode to non "hot-plug" mode. 1518 * Try to lock all boards before allowing the kstat_write. 1519 */ 1520 if (ac_enter_transition() == TRUE) 1521 fhc_bdlist_unlock(); 1522 else { 1523 /* cannot lock boards so fail */ 1524 mutex_exit(&ac_hot_plug_mode_mutex); 1525 return (-1); 1526 } 1527 1528 /* 1529 * We need to display a Warning about hot-plugging any 1530 * boards. This message is only needed when we are 1531 * transitioning out of "hot-plug" mode. 1532 */ 1533 cmn_err(CE_WARN, "This machine is being taken out of " 1534 "hot-plug mode."); 1535 cmn_err(CE_CONT, "Do not attempt to hot-plug boards " 1536 "or power supplies in this system until further notice."); 1537 1538 } else if (ac_hot_plug_timeout != (timeout_id_t)NULL) { 1539 /* 1540 * There is a pending timeout so we must already be 1541 * in non "hot-plug" mode. It doesn't matter if the 1542 * kstat request is a read or a write. 1543 * 1544 * We need to cancel the existing timeout. 1545 */ 1546 (void) untimeout(ac_hot_plug_timeout); 1547 ac_hot_plug_timeout = NULL; 1548 } 1549 1550 /* 1551 * create a new timeout. 1552 */ 1553 ac_hot_plug_timeout = timeout(ac_timeout, NULL, 1554 drv_usectohz(ac_hot_plug_timeout_interval * 1000000)); 1555 1556 mutex_exit(&ac_hot_plug_mode_mutex); 1557 return (0); 1558 } 1559 1560 static void 1561 ac_timeout(void *arg) 1562 { 1563 struct ac_soft_state *softsp; 1564 fhc_bd_t *board; 1565 1566 #ifdef lint 1567 arg = arg; 1568 #endif /* lint */ 1569 1570 ac_hot_plug_timeout = (timeout_id_t)NULL; 1571 1572 (void) fhc_bdlist_lock(-1); 1573 1574 /* 1575 * Foreach ac in the board list we need to 1576 * re-program the pcr into "hot-plug" mode. 1577 * We also program the pic register with the 1578 * bus pause timing 1579 */ 1580 board = fhc_bd_first(); 1581 while (board != NULL) { 1582 softsp = board->ac_softsp; 1583 if (softsp == NULL) { 1584 /* 1585 * This board must not have an AC. 1586 * Skip it and move on. 1587 */ 1588 board = fhc_bd_next(board); 1589 continue; 1590 } 1591 /* program the pcr into hot-plug mode */ 1592 *softsp->ac_mccr = AC_CLEAR_PCR(*softsp->ac_mccr); 1593 *softsp->ac_mccr = AC_SET_HOT_PLUG(*softsp->ac_mccr); 1594 1595 /* program the pic with the bus pause time value */ 1596 *softsp->ac_counter = AC_SET_PIC_BUS_PAUSE(softsp->board); 1597 1598 /* get the next board */ 1599 board = fhc_bd_next(board); 1600 } 1601 1602 ac_exit_transition(); 1603 1604 fhc_bdlist_unlock(); 1605 1606 /* 1607 * It is now safe to start hot-plugging again. We need 1608 * to display a message. 1609 */ 1610 cmn_err(CE_NOTE, "This machine is now in hot-plug mode."); 1611 cmn_err(CE_CONT, "Board and power supply hot-plug operations " 1612 "can be resumed."); 1613 } 1614 1615 /* 1616 * This function will acquire the lock and set the in_transition 1617 * bit for all the slots. If the slots are being used, 1618 * we return FALSE; else set in_transition and return TRUE. 1619 */ 1620 static int 1621 ac_enter_transition(void) 1622 { 1623 fhc_bd_t *list; 1624 sysc_cfga_stat_t *sysc_stat_lk; 1625 1626 /* mutex lock the structure */ 1627 (void) fhc_bdlist_lock(-1); 1628 1629 list = fhc_bd_clock(); 1630 1631 /* change the in_transition bit */ 1632 sysc_stat_lk = &list->sc; 1633 if (sysc_stat_lk->in_transition == TRUE) { 1634 fhc_bdlist_unlock(); 1635 return (FALSE); 1636 } else { 1637 sysc_stat_lk->in_transition = TRUE; 1638 return (TRUE); 1639 } 1640 } 1641 1642 /* 1643 * clear the in_transition bit for all the slots. 1644 */ 1645 static void 1646 ac_exit_transition(void) 1647 { 1648 fhc_bd_t *list; 1649 sysc_cfga_stat_t *sysc_stat_lk; 1650 1651 ASSERT(fhc_bdlist_locked()); 1652 1653 list = fhc_bd_clock(); 1654 1655 sysc_stat_lk = &list->sc; 1656 ASSERT(sysc_stat_lk->in_transition == TRUE); 1657 sysc_stat_lk->in_transition = FALSE; 1658 } 1659