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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 /*
  27  * A CPR derivative specifically for starfire/starcat
  28  * X86 doesn't make use of the quiesce interfaces, it's kept for simplicity.
  29  */
  30 
  31 #include <sys/types.h>
  32 #include <sys/systm.h>
  33 #include <sys/machparam.h>
  34 #include <sys/machsystm.h>
  35 #include <sys/ddi.h>
  36 #define SUNDDI_IMPL
  37 #include <sys/sunddi.h>
  38 #include <sys/sunndi.h>
  39 #include <sys/devctl.h>
  40 #include <sys/time.h>
  41 #include <sys/kmem.h>
  42 #include <nfs/lm.h>
  43 #include <sys/ddi_impldefs.h>
  44 #include <sys/ndi_impldefs.h>
  45 #include <sys/obpdefs.h>
  46 #include <sys/cmn_err.h>
  47 #include <sys/debug.h>
  48 #include <sys/errno.h>
  49 #include <sys/callb.h>
  50 #include <sys/clock.h>
  51 #include <sys/x_call.h>
  52 #include <sys/cpuvar.h>
  53 #include <sys/epm.h>
  54 #include <sys/vfs.h>
  55 #include <sys/promif.h>
  56 #include <sys/conf.h>
  57 #include <sys/cyclic.h>
  58 
  59 #include <sys/dr.h>
  60 #include <sys/dr_util.h>
  61 
  62 extern void     e_ddi_enter_driver_list(struct devnames *dnp, int *listcnt);
  63 extern void     e_ddi_exit_driver_list(struct devnames *dnp, int listcnt);
  64 extern int      is_pseudo_device(dev_info_t *dip);
  65 
  66 extern kmutex_t cpu_lock;
  67 extern dr_unsafe_devs_t dr_unsafe_devs;
  68 
  69 static int              dr_is_real_device(dev_info_t *dip);
  70 static int              dr_is_unsafe_major(major_t major);
  71 static int              dr_bypass_device(char *dname);
  72 static int              dr_check_dip(dev_info_t *dip, void *arg, uint_t ref);
  73 static int              dr_resolve_devname(dev_info_t *dip, char *buffer,
  74                                 char *alias);
  75 static sbd_error_t      *drerr_int(int e_code, uint64_t *arr, int idx,
  76                                 int majors);
  77 static int              dr_add_int(uint64_t *arr, int idx, int len,
  78                                 uint64_t val);
  79 
  80 int dr_pt_test_suspend(dr_handle_t *hp);
  81 
  82 /*
  83  * dr_quiesce.c interface
  84  * NOTE: states used internally by dr_suspend and dr_resume
  85  */
  86 typedef enum dr_suspend_state {
  87         DR_SRSTATE_BEGIN = 0,
  88         DR_SRSTATE_USER,
  89         DR_SRSTATE_DRIVER,
  90         DR_SRSTATE_FULL
  91 } suspend_state_t;
  92 
  93 struct dr_sr_handle {
  94         dr_handle_t             *sr_dr_handlep;
  95         dev_info_t              *sr_failed_dip;
  96         suspend_state_t         sr_suspend_state;
  97         uint_t                  sr_flags;
  98         uint64_t                sr_err_ints[DR_MAX_ERR_INT];
  99         int                     sr_err_idx;
 100 };
 101 
 102 #define SR_FLAG_WATCHDOG        0x1
 103 
 104 /*
 105  * XXX
 106  * This hack will go away before RTI.  Just for testing.
 107  * List of drivers to bypass when performing a suspend.
 108  */
 109 static char *dr_bypass_list[] = {
 110         ""
 111 };
 112 
 113 
 114 #define         SKIP_SYNC       /* bypass sync ops in dr_suspend */
 115 
 116 /*
 117  * dr_skip_user_threads is used to control if user threads should
 118  * be suspended.  If dr_skip_user_threads is true, the rest of the
 119  * flags are not used; if it is false, dr_check_user_stop_result
 120  * will be used to control whether or not we need to check suspend
 121  * result, and dr_allow_blocked_threads will be used to control
 122  * whether or not we allow suspend to continue if there are blocked
 123  * threads.  We allow all combinations of dr_check_user_stop_result
 124  * and dr_allow_block_threads, even though it might not make much
 125  * sense to not allow block threads when we don't even check stop
 126  * result.
 127  */
 128 static int      dr_skip_user_threads = 0;       /* default to FALSE */
 129 static int      dr_check_user_stop_result = 1;  /* default to TRUE */
 130 static int      dr_allow_blocked_threads = 1;   /* default to TRUE */
 131 
 132 #define DR_CPU_LOOP_MSEC        1000
 133 
 134 static void
 135 dr_stop_intr(void)
 136 {
 137         ASSERT(MUTEX_HELD(&cpu_lock));
 138 
 139         kpreempt_disable();
 140         cyclic_suspend();
 141 }
 142 
 143 static void
 144 dr_enable_intr(void)
 145 {
 146         ASSERT(MUTEX_HELD(&cpu_lock));
 147 
 148         cyclic_resume();
 149         kpreempt_enable();
 150 }
 151 
 152 dr_sr_handle_t *
 153 dr_get_sr_handle(dr_handle_t *hp)
 154 {
 155         dr_sr_handle_t *srh;
 156 
 157         srh = GETSTRUCT(dr_sr_handle_t, 1);
 158         srh->sr_dr_handlep = hp;
 159 
 160         return (srh);
 161 }
 162 
 163 void
 164 dr_release_sr_handle(dr_sr_handle_t *srh)
 165 {
 166         ASSERT(srh->sr_failed_dip == NULL);
 167         FREESTRUCT(srh, dr_sr_handle_t, 1);
 168 }
 169 
 170 static int
 171 dr_is_real_device(dev_info_t *dip)
 172 {
 173         struct regspec *regbuf = NULL;
 174         int length = 0;
 175         int rc;
 176 
 177         if (ddi_get_driver(dip) == NULL)
 178                 return (0);
 179 
 180         if (DEVI(dip)->devi_pm_flags & (PMC_NEEDS_SR|PMC_PARENTAL_SR))
 181                 return (1);
 182         if (DEVI(dip)->devi_pm_flags & PMC_NO_SR)
 183                 return (0);
 184 
 185         /*
 186          * now the general case
 187          */
 188         rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
 189             (caddr_t)&regbuf, &length);
 190         ASSERT(rc != DDI_PROP_NO_MEMORY);
 191         if (rc != DDI_PROP_SUCCESS) {
 192                 return (0);
 193         } else {
 194                 if ((length > 0) && (regbuf != NULL))
 195                         kmem_free(regbuf, length);
 196                 return (1);
 197         }
 198 }
 199 
 200 static int
 201 dr_is_unsafe_major(major_t major)
 202 {
 203         char    *dname, **cpp;
 204         int     i, ndevs;
 205 
 206         if ((dname = ddi_major_to_name(major)) == NULL) {
 207                 PR_QR("dr_is_unsafe_major: invalid major # %d\n", major);
 208                 return (0);
 209         }
 210 
 211         ndevs = dr_unsafe_devs.ndevs;
 212         for (i = 0, cpp = dr_unsafe_devs.devnames; i < ndevs; i++) {
 213                 if (strcmp(dname, *cpp++) == 0)
 214                         return (1);
 215         }
 216         return (0);
 217 }
 218 
 219 static int
 220 dr_bypass_device(char *dname)
 221 {
 222         int i;
 223         char **lname;
 224 
 225         if (dname == NULL)
 226                 return (0);
 227 
 228         /* check the bypass list */
 229         for (i = 0, lname = &dr_bypass_list[i]; **lname != '\0'; lname++) {
 230                 if (strcmp(dname, dr_bypass_list[i++]) == 0)
 231                         return (1);
 232         }
 233         return (0);
 234 }
 235 
 236 static int
 237 dr_resolve_devname(dev_info_t *dip, char *buffer, char *alias)
 238 {
 239         major_t devmajor;
 240         char    *aka, *name;
 241 
 242         *buffer = *alias = 0;
 243 
 244         if (dip == NULL)
 245                 return (-1);
 246 
 247         if ((name = ddi_get_name(dip)) == NULL)
 248                 name = "<null name>";
 249 
 250         aka = name;
 251 
 252         if ((devmajor = ddi_name_to_major(aka)) != DDI_MAJOR_T_NONE)
 253                 aka = ddi_major_to_name(devmajor);
 254 
 255         (void) strcpy(buffer, name);
 256 
 257         if (strcmp(name, aka))
 258                 (void) strcpy(alias, aka);
 259         else
 260                 *alias = 0;
 261 
 262         return (0);
 263 }
 264 
 265 struct dr_ref {
 266         int             *refcount;
 267         int             *refcount_non_gldv3;
 268         uint64_t        *arr;
 269         int             *idx;
 270         int             len;
 271 };
 272 
 273 /* ARGSUSED */
 274 static int
 275 dr_check_dip(dev_info_t *dip, void *arg, uint_t ref)
 276 {
 277         major_t         major;
 278         char            *dname;
 279         struct dr_ref   *rp = (struct dr_ref *)arg;
 280 
 281         if (dip == NULL)
 282                 return (DDI_WALK_CONTINUE);
 283 
 284         if (!dr_is_real_device(dip))
 285                 return (DDI_WALK_CONTINUE);
 286 
 287         dname = ddi_binding_name(dip);
 288 
 289         if (dr_bypass_device(dname))
 290                 return (DDI_WALK_CONTINUE);
 291 
 292         if (dname && ((major = ddi_name_to_major(dname)) != (major_t)-1)) {
 293                 if (ref && rp->refcount) {
 294                         *rp->refcount += ref;
 295                         PR_QR("\n  %s (major# %d) is referenced(%u)\n", dname,
 296                             major, ref);
 297                 }
 298                 if (ref && rp->refcount_non_gldv3) {
 299                         if (NETWORK_PHYSDRV(major) && !GLDV3_DRV(major))
 300                                 *rp->refcount_non_gldv3 += ref;
 301                 }
 302                 if (dr_is_unsafe_major(major) && i_ddi_devi_attached(dip)) {
 303                         PR_QR("\n  %s (major# %d) not hotpluggable\n", dname,
 304                             major);
 305                         if (rp->arr != NULL && rp->idx != NULL)
 306                                 *rp->idx = dr_add_int(rp->arr, *rp->idx,
 307                                     rp->len, (uint64_t)major);
 308                 }
 309         }
 310         return (DDI_WALK_CONTINUE);
 311 }
 312 
 313 static int
 314 dr_check_unsafe_major(dev_info_t *dip, void *arg)
 315 {
 316         return (dr_check_dip(dip, arg, 0));
 317 }
 318 
 319 
 320 /*ARGSUSED*/
 321 void
 322 dr_check_devices(dev_info_t *dip, int *refcount, dr_handle_t *handle,
 323     uint64_t *arr, int *idx, int len, int *refcount_non_gldv3)
 324 {
 325         struct dr_ref bref = {0};
 326 
 327         if (dip == NULL)
 328                 return;
 329 
 330         bref.refcount = refcount;
 331         bref.refcount_non_gldv3 = refcount_non_gldv3;
 332         bref.arr = arr;
 333         bref.idx = idx;
 334         bref.len = len;
 335 
 336         ASSERT(e_ddi_branch_held(dip));
 337         (void) e_ddi_branch_referenced(dip, dr_check_dip, &bref);
 338 }
 339 
 340 /*
 341  * The "dip" argument's parent (if it exists) must be held busy.
 342  */
 343 static int
 344 dr_suspend_devices(dev_info_t *dip, dr_sr_handle_t *srh)
 345 {
 346         dr_handle_t     *handle;
 347         major_t         major;
 348         char            *dname;
 349         int             circ;
 350 
 351         /*
 352          * If dip is the root node, it has no siblings and it is
 353          * always held. If dip is not the root node, dr_suspend_devices()
 354          * will be invoked with the parent held busy.
 355          */
 356         for (; dip != NULL; dip = ddi_get_next_sibling(dip)) {
 357                 char    d_name[40], d_alias[40], *d_info;
 358 
 359                 ndi_devi_enter(dip, &circ);
 360                 if (dr_suspend_devices(ddi_get_child(dip), srh)) {
 361                         ndi_devi_exit(dip, circ);
 362                         return (ENXIO);
 363                 }
 364                 ndi_devi_exit(dip, circ);
 365 
 366                 if (!dr_is_real_device(dip))
 367                         continue;
 368 
 369                 major = (major_t)-1;
 370                 if ((dname = ddi_binding_name(dip)) != NULL)
 371                         major = ddi_name_to_major(dname);
 372 
 373                 if (dr_bypass_device(dname)) {
 374                         PR_QR(" bypassed suspend of %s (major# %d)\n", dname,
 375                             major);
 376                         continue;
 377                 }
 378 
 379                 if (drmach_verify_sr(dip, 1)) {
 380                         PR_QR(" bypassed suspend of %s (major# %d)\n", dname,
 381                             major);
 382                         continue;
 383                 }
 384 
 385                 if ((d_info = ddi_get_name_addr(dip)) == NULL)
 386                         d_info = "<null>";
 387 
 388                 d_name[0] = 0;
 389                 if (dr_resolve_devname(dip, d_name, d_alias) == 0) {
 390                         if (d_alias[0] != 0) {
 391                                 prom_printf("\tsuspending %s@%s (aka %s)\n",
 392                                     d_name, d_info, d_alias);
 393                         } else {
 394                                 prom_printf("\tsuspending %s@%s\n", d_name,
 395                                     d_info);
 396                         }
 397                 } else {
 398                         prom_printf("\tsuspending %s@%s\n", dname, d_info);
 399                 }
 400 
 401                 if (devi_detach(dip, DDI_SUSPEND) != DDI_SUCCESS) {
 402                         prom_printf("\tFAILED to suspend %s@%s\n",
 403                             d_name[0] ? d_name : dname, d_info);
 404 
 405                         srh->sr_err_idx = dr_add_int(srh->sr_err_ints,
 406                             srh->sr_err_idx, DR_MAX_ERR_INT, (uint64_t)major);
 407 
 408                         ndi_hold_devi(dip);
 409                         srh->sr_failed_dip = dip;
 410 
 411                         handle = srh->sr_dr_handlep;
 412                         dr_op_err(CE_IGNORE, handle, ESBD_SUSPEND, "%s@%s",
 413                             d_name[0] ? d_name : dname, d_info);
 414 
 415                         return (DDI_FAILURE);
 416                 }
 417         }
 418 
 419         return (DDI_SUCCESS);
 420 }
 421 
 422 static void
 423 dr_resume_devices(dev_info_t *start, dr_sr_handle_t *srh)
 424 {
 425         dr_handle_t     *handle;
 426         dev_info_t      *dip, *next, *last = NULL;
 427         major_t         major;
 428         char            *bn;
 429         int             circ;
 430 
 431         major = (major_t)-1;
 432 
 433         /* attach in reverse device tree order */
 434         while (last != start) {
 435                 dip = start;
 436                 next = ddi_get_next_sibling(dip);
 437                 while (next != last && dip != srh->sr_failed_dip) {
 438                         dip = next;
 439                         next = ddi_get_next_sibling(dip);
 440                 }
 441                 if (dip == srh->sr_failed_dip) {
 442                         /* release hold acquired in dr_suspend_devices() */
 443                         srh->sr_failed_dip = NULL;
 444                         ndi_rele_devi(dip);
 445                 } else if (dr_is_real_device(dip) &&
 446                     srh->sr_failed_dip == NULL) {
 447 
 448                         if ((bn = ddi_binding_name(dip)) != NULL) {
 449                                 major = ddi_name_to_major(bn);
 450                         } else {
 451                                 bn = "<null>";
 452                         }
 453                         if (!dr_bypass_device(bn) &&
 454                             !drmach_verify_sr(dip, 0)) {
 455                                 char    d_name[40], d_alias[40], *d_info;
 456 
 457                                 d_name[0] = 0;
 458                                 d_info = ddi_get_name_addr(dip);
 459                                 if (d_info == NULL)
 460                                         d_info = "<null>";
 461 
 462                                 if (!dr_resolve_devname(dip, d_name, d_alias)) {
 463                                         if (d_alias[0] != 0) {
 464                                                 prom_printf("\tresuming "
 465                                                     "%s@%s (aka %s)\n", d_name,
 466                                                     d_info, d_alias);
 467                                         } else {
 468                                                 prom_printf("\tresuming "
 469                                                     "%s@%s\n", d_name, d_info);
 470                                         }
 471                                 } else {
 472                                         prom_printf("\tresuming %s@%s\n", bn,
 473                                             d_info);
 474                                 }
 475 
 476                                 if (devi_attach(dip, DDI_RESUME) !=
 477                                     DDI_SUCCESS) {
 478                                         /*
 479                                          * Print a console warning,
 480                                          * set an e_code of ESBD_RESUME,
 481                                          * and save the driver major
 482                                          * number in the e_rsc.
 483                                          */
 484                                         prom_printf("\tFAILED to resume %s@%s",
 485                                             d_name[0] ? d_name : bn, d_info);
 486 
 487                                         srh->sr_err_idx =
 488                                             dr_add_int(srh->sr_err_ints,
 489                                             srh->sr_err_idx, DR_MAX_ERR_INT,
 490                                             (uint64_t)major);
 491 
 492                                         handle = srh->sr_dr_handlep;
 493 
 494                                         dr_op_err(CE_IGNORE, handle,
 495                                             ESBD_RESUME, "%s@%s",
 496                                             d_name[0] ? d_name : bn, d_info);
 497                                 }
 498                         }
 499                 }
 500 
 501                 /* Hold parent busy while walking its children */
 502                 ndi_devi_enter(dip, &circ);
 503                 dr_resume_devices(ddi_get_child(dip), srh);
 504                 ndi_devi_exit(dip, circ);
 505                 last = dip;
 506         }
 507 }
 508 
 509 /*
 510  * True if thread is virtually stopped.  Similar to CPR_VSTOPPED
 511  * but from DR point of view.  These user threads are waiting in
 512  * the kernel.  Once they complete in the kernel, they will process
 513  * the stop signal and stop.
 514  */
 515 #define DR_VSTOPPED(t)                  \
 516         ((t)->t_state == TS_SLEEP && \
 517         (t)->t_wchan != NULL &&              \
 518         (t)->t_astflag &&            \
 519         ((t)->t_proc_flag & TP_CHKPT))
 520 
 521 /* ARGSUSED */
 522 static int
 523 dr_stop_user_threads(dr_sr_handle_t *srh)
 524 {
 525         int             count;
 526         int             bailout;
 527         dr_handle_t     *handle = srh->sr_dr_handlep;
 528         static fn_t     f = "dr_stop_user_threads";
 529         kthread_id_t    tp;
 530 
 531         extern void add_one_utstop();
 532         extern void utstop_timedwait(clock_t);
 533         extern void utstop_init(void);
 534 
 535 #define DR_UTSTOP_RETRY 4
 536 #define DR_UTSTOP_WAIT  hz
 537 
 538         if (dr_skip_user_threads)
 539                 return (DDI_SUCCESS);
 540 
 541         utstop_init();
 542 
 543         /* we need to try a few times to get past fork, etc. */
 544         srh->sr_err_idx = 0;
 545         for (count = 0; count < DR_UTSTOP_RETRY; count++) {
 546                 /* walk the entire threadlist */
 547                 mutex_enter(&pidlock);
 548                 for (tp = curthread->t_next; tp != curthread; tp = tp->t_next) {
 549                         proc_t *p = ttoproc(tp);
 550 
 551                         /* handle kernel threads separately */
 552                         if (p->p_as == &kas || p->p_stat == SZOMB)
 553                                 continue;
 554 
 555                         mutex_enter(&p->p_lock);
 556                         thread_lock(tp);
 557 
 558                         if (tp->t_state == TS_STOPPED) {
 559                                 /* add another reason to stop this thread */
 560                                 tp->t_schedflag &= ~TS_RESUME;
 561                         } else {
 562                                 tp->t_proc_flag |= TP_CHKPT;
 563 
 564                                 thread_unlock(tp);
 565                                 mutex_exit(&p->p_lock);
 566                                 add_one_utstop();
 567                                 mutex_enter(&p->p_lock);
 568                                 thread_lock(tp);
 569 
 570                                 aston(tp);
 571 
 572                                 if (ISWAKEABLE(tp) || ISWAITING(tp)) {
 573                                         setrun_locked(tp);
 574                                 }
 575 
 576                         }
 577 
 578                         /* grab thread if needed */
 579                         if (tp->t_state == TS_ONPROC && tp->t_cpu != CPU)
 580                                 poke_cpu(tp->t_cpu->cpu_id);
 581 
 582 
 583                         thread_unlock(tp);
 584                         mutex_exit(&p->p_lock);
 585                 }
 586                 mutex_exit(&pidlock);
 587 
 588 
 589                 /* let everything catch up */
 590                 utstop_timedwait(count * count * DR_UTSTOP_WAIT);
 591 
 592 
 593                 /* now, walk the threadlist again to see if we are done */
 594                 mutex_enter(&pidlock);
 595                 for (tp = curthread->t_next, bailout = 0;
 596                     tp != curthread; tp = tp->t_next) {
 597                         proc_t *p = ttoproc(tp);
 598 
 599                         /* handle kernel threads separately */
 600                         if (p->p_as == &kas || p->p_stat == SZOMB)
 601                                 continue;
 602 
 603                         /*
 604                          * If this thread didn't stop, and we don't allow
 605                          * unstopped blocked threads, bail.
 606                          */
 607                         thread_lock(tp);
 608                         if (!CPR_ISTOPPED(tp) &&
 609                             !(dr_allow_blocked_threads &&
 610                             DR_VSTOPPED(tp))) {
 611                                 bailout = 1;
 612                                 if (count == DR_UTSTOP_RETRY - 1) {
 613                                         /*
 614                                          * save the pid for later reporting
 615                                          */
 616                                         srh->sr_err_idx =
 617                                             dr_add_int(srh->sr_err_ints,
 618                                             srh->sr_err_idx, DR_MAX_ERR_INT,
 619                                             (uint64_t)p->p_pid);
 620 
 621                                         cmn_err(CE_WARN, "%s: "
 622                                             "failed to stop thread: "
 623                                             "process=%s, pid=%d",
 624                                             f, p->p_user.u_psargs, p->p_pid);
 625 
 626                                         PR_QR("%s: failed to stop thread: "
 627                                             "process=%s, pid=%d, t_id=0x%p, "
 628                                             "t_state=0x%x, t_proc_flag=0x%x, "
 629                                             "t_schedflag=0x%x\n",
 630                                             f, p->p_user.u_psargs, p->p_pid,
 631                                             (void *)tp, tp->t_state,
 632                                             tp->t_proc_flag, tp->t_schedflag);
 633                                 }
 634 
 635                         }
 636                         thread_unlock(tp);
 637                 }
 638                 mutex_exit(&pidlock);
 639 
 640                 /* were all the threads stopped? */
 641                 if (!bailout)
 642                         break;
 643         }
 644 
 645         /* were we unable to stop all threads after a few tries? */
 646         if (bailout) {
 647                 handle->h_err = drerr_int(ESBD_UTHREAD, srh->sr_err_ints,
 648                     srh->sr_err_idx, 0);
 649                 return (ESRCH);
 650         }
 651 
 652         return (DDI_SUCCESS);
 653 }
 654 
 655 static void
 656 dr_start_user_threads(void)
 657 {
 658         kthread_id_t tp;
 659 
 660         mutex_enter(&pidlock);
 661 
 662         /* walk all threads and release them */
 663         for (tp = curthread->t_next; tp != curthread; tp = tp->t_next) {
 664                 proc_t *p = ttoproc(tp);
 665 
 666                 /* skip kernel threads */
 667                 if (ttoproc(tp)->p_as == &kas)
 668                         continue;
 669 
 670                 mutex_enter(&p->p_lock);
 671                 tp->t_proc_flag &= ~TP_CHKPT;
 672                 mutex_exit(&p->p_lock);
 673 
 674                 thread_lock(tp);
 675                 if (CPR_ISTOPPED(tp)) {
 676                         /* back on the runq */
 677                         tp->t_schedflag |= TS_RESUME;
 678                         setrun_locked(tp);
 679                 }
 680                 thread_unlock(tp);
 681         }
 682 
 683         mutex_exit(&pidlock);
 684 }
 685 
 686 static void
 687 dr_signal_user(int sig)
 688 {
 689         struct proc *p;
 690 
 691         mutex_enter(&pidlock);
 692 
 693         for (p = practive; p != NULL; p = p->p_next) {
 694                 /* only user threads */
 695                 if (p->p_exec == NULL || p->p_stat == SZOMB ||
 696                     p == proc_init || p == ttoproc(curthread))
 697                         continue;
 698 
 699                 mutex_enter(&p->p_lock);
 700                 sigtoproc(p, NULL, sig);
 701                 mutex_exit(&p->p_lock);
 702         }
 703 
 704         mutex_exit(&pidlock);
 705 
 706         /* add a bit of delay */
 707         delay(hz);
 708 }
 709 
 710 void
 711 dr_resume(dr_sr_handle_t *srh)
 712 {
 713         switch (srh->sr_suspend_state) {
 714         case DR_SRSTATE_FULL:
 715 
 716                 ASSERT(MUTEX_HELD(&cpu_lock));
 717 
 718                 /*
 719                  * Prevent false alarm in tod_validate() due to tod
 720                  * value change between suspend and resume
 721                  */
 722                 mutex_enter(&tod_lock);
 723                 tod_status_set(TOD_DR_RESUME_DONE);
 724                 mutex_exit(&tod_lock);
 725 
 726                 dr_enable_intr();       /* enable intr & clock */
 727 
 728                 start_cpus();
 729                 mutex_exit(&cpu_lock);
 730 
 731                 /*
 732                  * This should only be called if drmach_suspend_last()
 733                  * was called and state transitioned to DR_SRSTATE_FULL
 734                  * to prevent resume attempts on device instances that
 735                  * were not previously suspended.
 736                  */
 737                 drmach_resume_first();
 738 
 739                 /* FALLTHROUGH */
 740 
 741         case DR_SRSTATE_DRIVER:
 742                 /*
 743                  * resume drivers
 744                  */
 745                 srh->sr_err_idx = 0;
 746 
 747                 /* no parent dip to hold busy */
 748                 dr_resume_devices(ddi_root_node(), srh);
 749 
 750                 if (srh->sr_err_idx && srh->sr_dr_handlep) {
 751                         (srh->sr_dr_handlep)->h_err = drerr_int(ESBD_RESUME,
 752                             srh->sr_err_ints, srh->sr_err_idx, 1);
 753                 }
 754 
 755                 /*
 756                  * resume the lock manager
 757                  */
 758                 lm_cprresume();
 759 
 760                 /* FALLTHROUGH */
 761 
 762         case DR_SRSTATE_USER:
 763                 /*
 764                  * finally, resume user threads
 765                  */
 766                 if (!dr_skip_user_threads) {
 767                         prom_printf("DR: resuming user threads...\n");
 768                         dr_start_user_threads();
 769                 }
 770                 /* FALLTHROUGH */
 771 
 772         case DR_SRSTATE_BEGIN:
 773         default:
 774                 /*
 775                  * let those who care know that we've just resumed
 776                  */
 777                 PR_QR("sending SIGTHAW...\n");
 778                 dr_signal_user(SIGTHAW);
 779                 break;
 780         }
 781 
 782         prom_printf("DR: resume COMPLETED\n");
 783 }
 784 
 785 int
 786 dr_suspend(dr_sr_handle_t *srh)
 787 {
 788         dr_handle_t     *handle;
 789         int             force;
 790         int             dev_errs_idx;
 791         uint64_t        dev_errs[DR_MAX_ERR_INT];
 792         int             rc = DDI_SUCCESS;
 793 
 794         handle = srh->sr_dr_handlep;
 795 
 796         force = dr_cmd_flags(handle) & SBD_FLAG_FORCE;
 797 
 798         prom_printf("\nDR: suspending user threads...\n");
 799         srh->sr_suspend_state = DR_SRSTATE_USER;
 800         if (((rc = dr_stop_user_threads(srh)) != DDI_SUCCESS) &&
 801             dr_check_user_stop_result) {
 802                 dr_resume(srh);
 803                 return (rc);
 804         }
 805 
 806         if (!force) {
 807                 struct dr_ref drc = {0};
 808 
 809                 prom_printf("\nDR: checking devices...\n");
 810                 dev_errs_idx = 0;
 811 
 812                 drc.arr = dev_errs;
 813                 drc.idx = &dev_errs_idx;
 814                 drc.len = DR_MAX_ERR_INT;
 815 
 816                 /*
 817                  * Since the root node can never go away, it
 818                  * doesn't have to be held.
 819                  */
 820                 ddi_walk_devs(ddi_root_node(), dr_check_unsafe_major, &drc);
 821                 if (dev_errs_idx) {
 822                         handle->h_err = drerr_int(ESBD_UNSAFE, dev_errs,
 823                             dev_errs_idx, 1);
 824                         dr_resume(srh);
 825                         return (DDI_FAILURE);
 826                 }
 827                 PR_QR("done\n");
 828         } else {
 829                 prom_printf("\nDR: dr_suspend invoked with force flag\n");
 830         }
 831 
 832 #ifndef SKIP_SYNC
 833         /*
 834          * This sync swap out all user pages
 835          */
 836         vfs_sync(SYNC_ALL);
 837 #endif
 838 
 839         /*
 840          * special treatment for lock manager
 841          */
 842         lm_cprsuspend();
 843 
 844 #ifndef SKIP_SYNC
 845         /*
 846          * sync the file system in case we never make it back
 847          */
 848         sync();
 849 #endif
 850 
 851         /*
 852          * now suspend drivers
 853          */
 854         prom_printf("DR: suspending drivers...\n");
 855         srh->sr_suspend_state = DR_SRSTATE_DRIVER;
 856         srh->sr_err_idx = 0;
 857         /* No parent to hold busy */
 858         if ((rc = dr_suspend_devices(ddi_root_node(), srh)) != DDI_SUCCESS) {
 859                 if (srh->sr_err_idx && srh->sr_dr_handlep) {
 860                         (srh->sr_dr_handlep)->h_err = drerr_int(ESBD_SUSPEND,
 861                             srh->sr_err_ints, srh->sr_err_idx, 1);
 862                 }
 863                 dr_resume(srh);
 864                 return (rc);
 865         }
 866 
 867         drmach_suspend_last();
 868 
 869         /*
 870          * finally, grab all cpus
 871          */
 872         srh->sr_suspend_state = DR_SRSTATE_FULL;
 873 
 874         mutex_enter(&cpu_lock);
 875         pause_cpus(NULL);
 876         dr_stop_intr();
 877 
 878         return (rc);
 879 }
 880 
 881 int
 882 dr_pt_test_suspend(dr_handle_t *hp)
 883 {
 884         dr_sr_handle_t *srh;
 885         int             err;
 886         uint_t          psmerr;
 887         static fn_t     f = "dr_pt_test_suspend";
 888 
 889         PR_QR("%s...\n", f);
 890 
 891         srh = dr_get_sr_handle(hp);
 892         if ((err = dr_suspend(srh)) == DDI_SUCCESS) {
 893                 dr_resume(srh);
 894                 if ((hp->h_err) && ((psmerr = hp->h_err->e_code) != 0)) {
 895                         PR_QR("%s: error on dr_resume()", f);
 896                         switch (psmerr) {
 897                         case ESBD_RESUME:
 898                                 PR_QR("Couldn't resume devices: %s\n",
 899                                     DR_GET_E_RSC(hp->h_err));
 900                                 break;
 901 
 902                         case ESBD_KTHREAD:
 903                                 PR_ALL("psmerr is ESBD_KTHREAD\n");
 904                                 break;
 905                         default:
 906                                 PR_ALL("Resume error unknown = %d\n", psmerr);
 907                                 break;
 908                         }
 909                 }
 910         } else {
 911                 PR_ALL("%s: dr_suspend() failed, err = 0x%x\n", f, err);
 912                 psmerr = hp->h_err ? hp->h_err->e_code : ESBD_NOERROR;
 913                 switch (psmerr) {
 914                 case ESBD_UNSAFE:
 915                         PR_ALL("Unsafe devices (major #): %s\n",
 916                             DR_GET_E_RSC(hp->h_err));
 917                         break;
 918 
 919                 case ESBD_RTTHREAD:
 920                         PR_ALL("RT threads (PIDs): %s\n",
 921                             DR_GET_E_RSC(hp->h_err));
 922                         break;
 923 
 924                 case ESBD_UTHREAD:
 925                         PR_ALL("User threads (PIDs): %s\n",
 926                             DR_GET_E_RSC(hp->h_err));
 927                         break;
 928 
 929                 case ESBD_SUSPEND:
 930                         PR_ALL("Non-suspendable devices (major #): %s\n",
 931                             DR_GET_E_RSC(hp->h_err));
 932                         break;
 933 
 934                 case ESBD_RESUME:
 935                         PR_ALL("Could not resume devices (major #): %s\n",
 936                             DR_GET_E_RSC(hp->h_err));
 937                         break;
 938 
 939                 case ESBD_KTHREAD:
 940                         PR_ALL("psmerr is ESBD_KTHREAD\n");
 941                         break;
 942 
 943                 case ESBD_NOERROR:
 944                         PR_ALL("sbd_error_t error code not set\n");
 945                         break;
 946 
 947                 default:
 948                         PR_ALL("Unknown error psmerr = %d\n", psmerr);
 949                         break;
 950                 }
 951         }
 952         dr_release_sr_handle(srh);
 953 
 954         return (0);
 955 }
 956 
 957 /*
 958  * Add a new integer value to the end of an array.  Don't allow duplicates to
 959  * appear in the array, and don't allow the array to overflow.  Return the new
 960  * total number of entries in the array.
 961  */
 962 static int
 963 dr_add_int(uint64_t *arr, int idx, int len, uint64_t val)
 964 {
 965         int i;
 966 
 967         if (arr == NULL)
 968                 return (0);
 969 
 970         if (idx >= len)
 971                 return (idx);
 972 
 973         for (i = 0; i < idx; i++) {
 974                 if (arr[i] == val)
 975                         return (idx);
 976         }
 977 
 978         arr[idx++] = val;
 979 
 980         return (idx);
 981 }
 982 
 983 /*
 984  * Construct an sbd_error_t featuring a string representation of an array of
 985  * integers as its e_rsc.
 986  */
 987 static sbd_error_t *
 988 drerr_int(int e_code, uint64_t *arr, int idx, int majors)
 989 {
 990         int             i, n, buf_len, buf_idx, buf_avail;
 991         char            *dname;
 992         char            *buf;
 993         sbd_error_t     *new_sbd_err;
 994         static char     s_ellipsis[] = "...";
 995 
 996         if (arr == NULL || idx <= 0)
 997                 return (NULL);
 998 
 999         /* MAXPATHLEN is the size of the e_rsc field in sbd_error_t. */
1000         buf = (char *)kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1001 
1002         /*
1003          * This is the total working area of the buffer.  It must be computed
1004          * as the size of 'buf', minus reserved space for the null terminator
1005          * and the ellipsis string.
1006          */
1007         buf_len = MAXPATHLEN - (strlen(s_ellipsis) + 1);
1008 
1009         /* Construct a string representation of the array values */
1010         for (buf_idx = 0, i = 0; i < idx; i++) {
1011                 buf_avail = buf_len - buf_idx;
1012                 if (majors) {
1013                         dname = ddi_major_to_name(arr[i]);
1014                         if (dname) {
1015                                 n = snprintf(&buf[buf_idx], buf_avail, "%s, ",
1016                                     dname);
1017                         } else {
1018                                 n = snprintf(&buf[buf_idx], buf_avail,
1019                                     "major %" PRIu64 ", ", arr[i]);
1020                         }
1021                 } else {
1022                         n = snprintf(&buf[buf_idx], buf_avail, "%" PRIu64 ", ",
1023                             arr[i]);
1024                 }
1025 
1026                 /* An ellipsis gets appended when no more values fit */
1027                 if (n >= buf_avail) {
1028                         (void) strcpy(&buf[buf_idx], s_ellipsis);
1029                         break;
1030                 }
1031 
1032                 buf_idx += n;
1033         }
1034 
1035         /* If all the contents fit, remove the trailing comma */
1036         if (n < buf_avail) {
1037                 buf[--buf_idx] = '\0';
1038                 buf[--buf_idx] = '\0';
1039         }
1040 
1041         /* Return an sbd_error_t with the buffer and e_code */
1042         new_sbd_err = drerr_new(1, e_code, buf);
1043         kmem_free(buf, MAXPATHLEN);
1044         return (new_sbd_err);
1045 }