Print this page
XXXX pass in cpu_pause_func via pause_cpus
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/cpr/cpr_main.c
+++ new/usr/src/uts/common/cpr/cpr_main.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /*
27 27 * This module contains the guts of checkpoint-resume mechanism.
28 28 * All code in this module is platform independent.
29 29 */
30 30
31 31 #include <sys/types.h>
32 32 #include <sys/errno.h>
33 33 #include <sys/callb.h>
34 34 #include <sys/processor.h>
35 35 #include <sys/machsystm.h>
36 36 #include <sys/clock.h>
37 37 #include <sys/vfs.h>
38 38 #include <sys/kmem.h>
39 39 #include <nfs/lm.h>
40 40 #include <sys/systm.h>
41 41 #include <sys/cpr.h>
42 42 #include <sys/bootconf.h>
43 43 #include <sys/cyclic.h>
44 44 #include <sys/filio.h>
45 45 #include <sys/fs/ufs_filio.h>
46 46 #include <sys/epm.h>
47 47 #include <sys/modctl.h>
48 48 #include <sys/reboot.h>
49 49 #include <sys/kdi.h>
50 50 #include <sys/promif.h>
51 51 #include <sys/srn.h>
52 52 #include <sys/cpr_impl.h>
53 53
54 54 #define PPM(dip) ((dev_info_t *)DEVI(dip)->devi_pm_ppm)
55 55
56 56 extern struct cpr_terminator cpr_term;
57 57
58 58 extern int cpr_alloc_statefile(int);
59 59 extern void cpr_start_kernel_threads(void);
60 60 extern void cpr_abbreviate_devpath(char *, char *);
61 61 extern void cpr_convert_promtime(cpr_time_t *);
62 62 extern void cpr_send_notice(void);
63 63 extern void cpr_set_bitmap_size(void);
64 64 extern void cpr_stat_init();
65 65 extern void cpr_statef_close(void);
66 66 extern void flush_windows(void);
67 67 extern void (*srn_signal)(int, int);
68 68 extern void init_cpu_syscall(struct cpu *);
69 69 extern void i_cpr_pre_resume_cpus();
70 70 extern void i_cpr_post_resume_cpus();
71 71 extern int cpr_is_ufs(struct vfs *);
72 72
73 73 extern int pm_powering_down;
74 74 extern kmutex_t srn_clone_lock;
75 75 extern int srn_inuse;
76 76
77 77 static int cpr_suspend(int);
78 78 static int cpr_resume(int);
79 79 static void cpr_suspend_init(int);
80 80 #if defined(__x86)
81 81 static int cpr_suspend_cpus(void);
82 82 static void cpr_resume_cpus(void);
↓ open down ↓ |
82 lines elided |
↑ open up ↑ |
83 83 #endif
84 84 static int cpr_all_online(void);
85 85 static void cpr_restore_offline(void);
86 86
87 87 cpr_time_t wholecycle_tv;
88 88 int cpr_suspend_succeeded;
89 89 pfn_t curthreadpfn;
90 90 int curthreadremapped;
91 91
92 92 extern cpuset_t cpu_ready_set;
93 -extern void *(*cpu_pause_func)(void *);
94 93
95 94 extern processorid_t i_cpr_bootcpuid(void);
96 95 extern cpu_t *i_cpr_bootcpu(void);
97 96 extern void tsc_adjust_delta(hrtime_t tdelta);
98 97 extern void tsc_resume(void);
99 98 extern int tsc_resume_in_cyclic;
100 99
101 100 /*
102 101 * Set this variable to 1, to have device drivers resume in an
103 102 * uniprocessor environment. This is to allow drivers that assume
104 103 * that they resume on a UP machine to continue to work. Should be
105 104 * deprecated once the broken drivers are fixed
106 105 */
107 106 int cpr_resume_uniproc = 0;
108 107
109 108 /*
110 109 * save or restore abort_enable; this prevents a drop
111 110 * to kadb or prom during cpr_resume_devices() when
112 111 * there is no kbd present; see abort_sequence_enter()
113 112 */
114 113 static void
115 114 cpr_sae(int stash)
116 115 {
117 116 static int saved_ae = -1;
118 117
119 118 if (stash) {
120 119 saved_ae = abort_enable;
121 120 abort_enable = 0;
122 121 } else if (saved_ae != -1) {
123 122 abort_enable = saved_ae;
124 123 saved_ae = -1;
125 124 }
126 125 }
127 126
128 127
129 128 /*
130 129 * The main switching point for cpr, this routine starts the ckpt
131 130 * and state file saving routines; on resume the control is
132 131 * returned back to here and it then calls the resume routine.
133 132 */
134 133 int
135 134 cpr_main(int sleeptype)
136 135 {
137 136 int rc, rc2;
138 137 label_t saveq;
139 138 klwp_t *tlwp = ttolwp(curthread);
140 139
141 140 if (sleeptype == CPR_TODISK) {
142 141 if ((rc = cpr_default_setup(1)) != 0)
143 142 return (rc);
144 143 ASSERT(tlwp);
145 144 saveq = tlwp->lwp_qsav;
146 145 }
147 146
148 147 if (sleeptype == CPR_TORAM) {
149 148 rc = cpr_suspend(sleeptype);
150 149 PMD(PMD_SX, ("cpr_suspend rets %x\n", rc))
151 150 if (rc == 0) {
152 151 int i_cpr_power_down(int sleeptype);
153 152
154 153 /*
155 154 * From this point on, we should be at a high
156 155 * spl, interrupts disabled, and all but one
157 156 * cpu's paused (effectively UP/single threaded).
158 157 * So this is were we want to put ASSERTS()
159 158 * to let us know otherwise.
160 159 */
161 160 ASSERT(cpus_paused());
162 161
163 162 /*
164 163 * Now do the work of actually putting this
165 164 * machine to sleep!
166 165 */
167 166 rc = i_cpr_power_down(sleeptype);
168 167 if (rc == 0) {
169 168 PMD(PMD_SX, ("back from successful suspend\n"))
170 169 }
171 170 /*
172 171 * We do care about the return value from cpr_resume
173 172 * at this point, as it will tell us if one of the
174 173 * resume functions failed (cpr_resume_devices())
175 174 * However, for this to return and _not_ panic, means
176 175 * that we must be in one of the test functions. So
177 176 * check for that and return an appropriate message.
178 177 */
179 178 rc2 = cpr_resume(sleeptype);
180 179 if (rc2 != 0) {
181 180 ASSERT(cpr_test_point > 0);
182 181 cmn_err(CE_NOTE,
183 182 "cpr_resume returned non-zero: %d\n", rc2);
184 183 PMD(PMD_SX, ("cpr_resume rets %x\n", rc2))
185 184 }
186 185 ASSERT(!cpus_paused());
187 186 } else {
188 187 PMD(PMD_SX, ("failed suspend, resuming\n"))
189 188 rc = cpr_resume(sleeptype);
190 189 }
191 190 return (rc);
192 191 }
193 192 /*
194 193 * Remember where we are for resume after reboot
195 194 */
196 195 if (!setjmp(&tlwp->lwp_qsav)) {
197 196 /*
198 197 * try to checkpoint the system, if failed return back
199 198 * to userland, otherwise power off.
200 199 */
201 200 rc = cpr_suspend(sleeptype);
202 201 if (rc || cpr_reusable_mode) {
203 202 /*
204 203 * We don't really want to go down, or
205 204 * something went wrong in suspend, do what we can
206 205 * to put the system back to an operable state then
207 206 * return back to userland.
208 207 */
209 208 PMD(PMD_SX, ("failed suspend, resuming\n"))
210 209 (void) cpr_resume(sleeptype);
211 210 PMD(PMD_SX, ("back from failed suspend resume\n"))
212 211 }
213 212 } else {
214 213 /*
215 214 * This is the resumed side of longjmp, restore the previous
216 215 * longjmp pointer if there is one so this will be transparent
217 216 * to the world.
218 217 * This path is only for CPR_TODISK, where we reboot
219 218 */
220 219 ASSERT(sleeptype == CPR_TODISK);
221 220 tlwp->lwp_qsav = saveq;
222 221 CPR->c_flags &= ~C_SUSPENDING;
223 222 CPR->c_flags |= C_RESUMING;
224 223
225 224 /*
226 225 * resume the system back to the original state
227 226 */
228 227 rc = cpr_resume(sleeptype);
229 228 PMD(PMD_SX, ("back from successful suspend; resume rets %x\n",
230 229 rc))
231 230 }
232 231
233 232 (void) cpr_default_setup(0);
234 233
235 234 return (rc);
236 235 }
237 236
238 237
239 238 #if defined(__sparc)
240 239
241 240 /*
242 241 * check/disable or re-enable UFS logging
243 242 */
244 243 static void
245 244 cpr_log_status(int enable, int *svstat, vnode_t *vp)
246 245 {
247 246 int cmd, status, error;
248 247 char *str, *able;
249 248 fiolog_t fl;
250 249 refstr_t *mntpt;
251 250
252 251 str = "cpr_log_status";
253 252 bzero(&fl, sizeof (fl));
254 253 fl.error = FIOLOG_ENONE;
255 254
256 255 /*
257 256 * when disabling, first get and save logging status (0 or 1)
258 257 */
259 258 if (enable == 0) {
260 259 if (error = VOP_IOCTL(vp, _FIOISLOG,
261 260 (uintptr_t)&status, FKIOCTL, CRED(), NULL, NULL)) {
262 261 mntpt = vfs_getmntpoint(vp->v_vfsp);
263 262 prom_printf("%s: \"%s\", cant get logging "
264 263 "status, error %d\n", str, refstr_value(mntpt),
265 264 error);
266 265 refstr_rele(mntpt);
267 266 return;
268 267 }
269 268 *svstat = status;
270 269 if (cpr_debug & CPR_DEBUG5) {
271 270 mntpt = vfs_getmntpoint(vp->v_vfsp);
272 271 errp("%s: \"%s\", logging status = %d\n",
273 272 str, refstr_value(mntpt), status);
274 273 refstr_rele(mntpt);
275 274 };
276 275
277 276 able = "disable";
278 277 cmd = _FIOLOGDISABLE;
279 278 } else {
280 279 able = "enable";
281 280 cmd = _FIOLOGENABLE;
282 281 }
283 282
284 283 /*
285 284 * disable or re-enable logging when the saved status is 1
286 285 */
287 286 if (*svstat == 1) {
288 287 error = VOP_IOCTL(vp, cmd, (uintptr_t)&fl,
289 288 FKIOCTL, CRED(), NULL, NULL);
290 289 if (error) {
291 290 mntpt = vfs_getmntpoint(vp->v_vfsp);
292 291 prom_printf("%s: \"%s\", cant %s logging, error %d\n",
293 292 str, refstr_value(mntpt), able, error);
294 293 refstr_rele(mntpt);
295 294 } else {
296 295 if (cpr_debug & CPR_DEBUG5) {
297 296 mntpt = vfs_getmntpoint(vp->v_vfsp);
298 297 errp("%s: \"%s\", logging is now %sd\n",
299 298 str, refstr_value(mntpt), able);
300 299 refstr_rele(mntpt);
301 300 };
302 301 }
303 302 }
304 303
305 304 /*
306 305 * when enabling logging, reset the saved status
307 306 * to unknown for next time
308 307 */
309 308 if (enable)
310 309 *svstat = -1;
311 310 }
312 311
313 312 /*
314 313 * enable/disable UFS logging on filesystems containing cpr_default_path
315 314 * and cpr statefile. since the statefile can be on any fs, that fs
316 315 * needs to be handled separately. this routine and cprboot expect that
317 316 * CPR_CONFIG and CPR_DEFAULT both reside on the same fs, rootfs. cprboot
318 317 * is loaded from the device with rootfs and uses the same device to open
319 318 * both CPR_CONFIG and CPR_DEFAULT (see common/support.c). moving either
320 319 * file outside of rootfs would cause errors during cprboot, plus cpr and
321 320 * fsck problems with the new fs if logging were enabled.
322 321 */
323 322
324 323 static int
325 324 cpr_ufs_logging(int enable)
326 325 {
327 326 static int def_status = -1, sf_status = -1;
328 327 struct vfs *vfsp;
329 328 char *fname;
330 329 vnode_t *vp;
331 330 int error;
332 331
333 332 if (cpr_reusable_mode)
334 333 return (0);
335 334
336 335 if (error = cpr_open_deffile(FREAD, &vp))
337 336 return (error);
338 337 vfsp = vp->v_vfsp;
339 338 if (!cpr_is_ufs(vfsp)) {
340 339 (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
341 340 VN_RELE(vp);
342 341 return (0);
343 342 }
344 343
345 344 cpr_log_status(enable, &def_status, vp);
346 345 (void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
347 346 VN_RELE(vp);
348 347
349 348 fname = cpr_build_statefile_path();
350 349 if (fname == NULL)
351 350 return (ENOENT);
352 351 if (error = vn_open(fname, UIO_SYSSPACE, FCREAT|FWRITE,
353 352 0600, &vp, CRCREAT, 0)) {
354 353 prom_printf("cpr_ufs_logging: cant open/create \"%s\", "
355 354 "error %d\n", fname, error);
356 355 return (error);
357 356 }
358 357
359 358 /*
360 359 * check logging status for the statefile if it resides
361 360 * on a different fs and the type is a regular file
362 361 */
363 362 if (vp->v_vfsp != vfsp && vp->v_type == VREG)
364 363 cpr_log_status(enable, &sf_status, vp);
365 364 (void) VOP_CLOSE(vp, FWRITE, 1, (offset_t)0, CRED(), NULL);
366 365 VN_RELE(vp);
367 366
368 367 return (0);
369 368 }
370 369 #endif
371 370
372 371
373 372 /*
374 373 * Check if klmmod is loaded and call a lock manager service; if klmmod
375 374 * is not loaded, the services aren't needed and a call would trigger a
376 375 * modload, which would block since another thread would never run.
377 376 */
378 377 static void
379 378 cpr_lock_mgr(void (*service)(void))
380 379 {
381 380 if (mod_find_by_filename(NULL, "misc/klmmod") != NULL)
382 381 (*service)();
383 382 }
384 383
385 384 int
386 385 cpr_suspend_cpus(void)
387 386 {
388 387 int ret = 0;
389 388 extern void *i_cpr_save_context(void *arg);
390 389
391 390 mutex_enter(&cpu_lock);
392 391
393 392 /*
394 393 * the machine could not have booted without a bootcpu
395 394 */
396 395 ASSERT(i_cpr_bootcpu() != NULL);
397 396
398 397 /*
399 398 * bring all the offline cpus online
400 399 */
401 400 if ((ret = cpr_all_online())) {
402 401 mutex_exit(&cpu_lock);
403 402 return (ret);
404 403 }
405 404
406 405 /*
407 406 * Set the affinity to be the boot processor
408 407 * This is cleared in either cpr_resume_cpus() or cpr_unpause_cpus()
↓ open down ↓ |
305 lines elided |
↑ open up ↑ |
409 408 */
410 409 affinity_set(i_cpr_bootcpuid());
411 410
412 411 ASSERT(CPU->cpu_id == 0);
413 412
414 413 PMD(PMD_SX, ("curthread running on bootcpu\n"))
415 414
416 415 /*
417 416 * pause all other running CPUs and save the CPU state at the sametime
418 417 */
419 - cpu_pause_func = i_cpr_save_context;
420 - pause_cpus(NULL);
418 + pause_cpus(NULL, i_cpr_save_context);
421 419
422 420 mutex_exit(&cpu_lock);
423 421
424 422 return (0);
425 423 }
426 424
427 425 /*
428 426 * Take the system down to a checkpointable state and write
429 427 * the state file, the following are sequentially executed:
430 428 *
431 429 * - Request all user threads to stop themselves
432 430 * - push out and invalidate user pages
433 431 * - bring statefile inode incore to prevent a miss later
434 432 * - request all daemons to stop
435 433 * - check and make sure all threads are stopped
436 434 * - sync the file system
437 435 * - suspend all devices
438 436 * - block intrpts
439 437 * - dump system state and memory to state file
440 438 * - SPARC code will not be called with CPR_TORAM, caller filters
441 439 */
442 440 static int
443 441 cpr_suspend(int sleeptype)
444 442 {
445 443 #if defined(__sparc)
446 444 int sf_realloc, nverr;
447 445 #endif
448 446 int rc = 0;
449 447 int skt_rc = 0;
450 448
451 449 PMD(PMD_SX, ("cpr_suspend %x\n", sleeptype))
452 450 cpr_set_substate(C_ST_SUSPEND_BEGIN);
453 451
454 452 cpr_suspend_init(sleeptype);
455 453
456 454 cpr_save_time();
457 455
458 456 cpr_tod_get(&wholecycle_tv);
459 457 CPR_STAT_EVENT_START("Suspend Total");
460 458
461 459 i_cpr_alloc_cpus();
462 460
463 461 #if defined(__sparc)
464 462 ASSERT(sleeptype == CPR_TODISK);
465 463 if (!cpr_reusable_mode) {
466 464 /*
467 465 * We need to validate default file before fs
468 466 * functionality is disabled.
469 467 */
470 468 if (rc = cpr_validate_definfo(0))
471 469 return (rc);
472 470 }
473 471 i_cpr_save_machdep_info();
474 472 #endif
475 473
476 474 PMD(PMD_SX, ("cpr_suspend: stop scans\n"))
477 475 /* Stop PM scans ASAP */
478 476 (void) callb_execute_class(CB_CL_CPR_PM, CB_CODE_CPR_CHKPT);
479 477
480 478 pm_dispatch_to_dep_thread(PM_DEP_WK_CPR_SUSPEND,
481 479 NULL, NULL, PM_DEP_WAIT, NULL, 0);
482 480
483 481 #if defined(__sparc)
484 482 ASSERT(sleeptype == CPR_TODISK);
485 483 cpr_set_substate(C_ST_MP_OFFLINE);
486 484 if (rc = cpr_mp_offline())
487 485 return (rc);
488 486 #endif
489 487 /*
490 488 * Ask Xorg to suspend the frame buffer, and wait for it to happen
491 489 */
492 490 mutex_enter(&srn_clone_lock);
493 491 if (srn_signal) {
494 492 PMD(PMD_SX, ("cpr_suspend: (*srn_signal)(..., "
495 493 "SRN_SUSPEND_REQ)\n"))
496 494 srn_inuse = 1; /* because *(srn_signal) cv_waits */
497 495 (*srn_signal)(SRN_TYPE_APM, SRN_SUSPEND_REQ);
498 496 srn_inuse = 0;
499 497 } else {
500 498 PMD(PMD_SX, ("cpr_suspend: srn_signal NULL\n"))
501 499 }
502 500 mutex_exit(&srn_clone_lock);
503 501
504 502 /*
505 503 * Ask the user threads to stop by themselves, but
506 504 * if they don't or can't after 3 retries, we give up on CPR.
507 505 * The 3 retry is not a random number because 2 is possible if
508 506 * a thread has been forked before the parent thread is stopped.
509 507 */
510 508 CPR_DEBUG(CPR_DEBUG1, "\nstopping user threads...");
511 509 CPR_STAT_EVENT_START(" stop users");
512 510 cpr_set_substate(C_ST_STOP_USER_THREADS);
513 511 PMD(PMD_SX, ("cpr_suspend: stop user threads\n"))
514 512 if (rc = cpr_stop_user_threads())
515 513 return (rc);
516 514 CPR_STAT_EVENT_END(" stop users");
517 515 CPR_DEBUG(CPR_DEBUG1, "done\n");
518 516
519 517 PMD(PMD_SX, ("cpr_suspend: save direct levels\n"))
520 518 pm_save_direct_levels();
521 519
522 520 /*
523 521 * User threads are stopped. We will start communicating with the
524 522 * user via prom_printf (some debug output may have already happened)
525 523 * so let anybody who cares know about this (bug 4096122)
526 524 */
527 525 (void) callb_execute_class(CB_CL_CPR_PROMPRINTF, CB_CODE_CPR_CHKPT);
528 526
529 527 PMD(PMD_SX, ("cpr_suspend: send notice\n"))
530 528 #ifndef DEBUG
531 529 cpr_send_notice();
532 530 if (cpr_debug)
533 531 prom_printf("\n");
534 532 #endif
535 533
536 534 PMD(PMD_SX, ("cpr_suspend: POST USER callback\n"))
537 535 (void) callb_execute_class(CB_CL_CPR_POST_USER, CB_CODE_CPR_CHKPT);
538 536
539 537 /*
540 538 * Reattach any drivers which originally exported the
541 539 * no-involuntary-power-cycles property. We need to do this before
542 540 * stopping kernel threads because modload is implemented using
543 541 * a kernel thread.
544 542 */
545 543 cpr_set_substate(C_ST_PM_REATTACH_NOINVOL);
546 544 PMD(PMD_SX, ("cpr_suspend: reattach noinvol\n"))
547 545 if (!pm_reattach_noinvol())
548 546 return (ENXIO);
549 547
550 548 #if defined(__sparc)
551 549 ASSERT(sleeptype == CPR_TODISK);
552 550 /*
553 551 * if ufs logging is enabled, we need to disable before
554 552 * stopping kernel threads so that ufs delete and roll
555 553 * threads can do the work.
556 554 */
557 555 cpr_set_substate(C_ST_DISABLE_UFS_LOGGING);
558 556 if (rc = cpr_ufs_logging(0))
559 557 return (rc);
560 558
561 559 /*
562 560 * Use sync_all to swap out all user pages and find out how much
563 561 * extra space needed for user pages that don't have back store
564 562 * space left.
565 563 */
566 564 CPR_STAT_EVENT_START(" swapout upages");
567 565 vfs_sync(SYNC_ALL);
568 566 CPR_STAT_EVENT_END(" swapout upages");
569 567
570 568 cpr_set_bitmap_size();
571 569
572 570 alloc_statefile:
573 571 /*
574 572 * If our last state was C_ST_DUMP_NOSPC, we're trying to
575 573 * realloc the statefile, otherwise this is the first attempt.
576 574 */
577 575 sf_realloc = (CPR->c_substate == C_ST_DUMP_NOSPC) ? 1 : 0;
578 576
579 577 CPR_STAT_EVENT_START(" alloc statefile");
580 578 cpr_set_substate(C_ST_STATEF_ALLOC);
581 579 if (rc = cpr_alloc_statefile(sf_realloc)) {
582 580 if (sf_realloc)
583 581 errp("realloc failed\n");
584 582 return (rc);
585 583 }
586 584 CPR_STAT_EVENT_END(" alloc statefile");
587 585
588 586 /*
589 587 * Sync the filesystem to preserve its integrity.
590 588 *
591 589 * This sync is also used to flush out all B_DELWRI buffers
592 590 * (fs cache) which are mapped and neither dirty nor referenced
593 591 * before cpr_invalidate_pages destroys them.
594 592 * fsflush does similar thing.
595 593 */
596 594 sync();
597 595
598 596 /*
599 597 * destroy all clean file mapped kernel pages
600 598 */
601 599 CPR_STAT_EVENT_START(" clean pages");
602 600 CPR_DEBUG(CPR_DEBUG1, ("cleaning up mapped pages..."));
603 601 (void) callb_execute_class(CB_CL_CPR_VM, CB_CODE_CPR_CHKPT);
604 602 CPR_DEBUG(CPR_DEBUG1, ("done\n"));
605 603 CPR_STAT_EVENT_END(" clean pages");
606 604 #endif
607 605
608 606
609 607 /*
610 608 * Hooks needed by lock manager prior to suspending.
611 609 * Refer to code for more comments.
612 610 */
613 611 PMD(PMD_SX, ("cpr_suspend: lock mgr\n"))
614 612 cpr_lock_mgr(lm_cprsuspend);
615 613
616 614 /*
617 615 * Now suspend all the devices
618 616 */
619 617 CPR_STAT_EVENT_START(" stop drivers");
620 618 CPR_DEBUG(CPR_DEBUG1, "suspending drivers...");
621 619 cpr_set_substate(C_ST_SUSPEND_DEVICES);
622 620 pm_powering_down = 1;
623 621 PMD(PMD_SX, ("cpr_suspend: suspending devices\n"))
624 622 rc = cpr_suspend_devices(ddi_root_node());
625 623 pm_powering_down = 0;
626 624 if (rc)
627 625 return (rc);
628 626 CPR_DEBUG(CPR_DEBUG1, "done\n");
629 627 CPR_STAT_EVENT_END(" stop drivers");
630 628
631 629 /*
632 630 * Stop all daemon activities
633 631 */
634 632 cpr_set_substate(C_ST_STOP_KERNEL_THREADS);
635 633 PMD(PMD_SX, ("cpr_suspend: stopping kernel threads\n"))
636 634 if (skt_rc = cpr_stop_kernel_threads())
637 635 return (skt_rc);
638 636
639 637 PMD(PMD_SX, ("cpr_suspend: POST KERNEL callback\n"))
640 638 (void) callb_execute_class(CB_CL_CPR_POST_KERNEL, CB_CODE_CPR_CHKPT);
641 639
642 640 PMD(PMD_SX, ("cpr_suspend: reattach noinvol fini\n"))
643 641 pm_reattach_noinvol_fini();
644 642
645 643 cpr_sae(1);
646 644
647 645 PMD(PMD_SX, ("cpr_suspend: CPR CALLOUT callback\n"))
648 646 (void) callb_execute_class(CB_CL_CPR_CALLOUT, CB_CODE_CPR_CHKPT);
649 647
650 648 if (sleeptype == CPR_TODISK) {
651 649 /*
652 650 * It's safer to do tod_get before we disable all intr.
653 651 */
654 652 CPR_STAT_EVENT_START(" write statefile");
655 653 }
656 654
657 655 /*
658 656 * it's time to ignore the outside world, stop the real time
659 657 * clock and disable any further intrpt activity.
660 658 */
661 659 PMD(PMD_SX, ("cpr_suspend: handle xc\n"))
662 660 i_cpr_handle_xc(1); /* turn it on to disable xc assertion */
663 661
664 662 mutex_enter(&cpu_lock);
665 663 PMD(PMD_SX, ("cpr_suspend: cyclic suspend\n"))
666 664 cyclic_suspend();
667 665 mutex_exit(&cpu_lock);
668 666
669 667 /*
670 668 * Due to the different methods of resuming the system between
671 669 * CPR_TODISK (boot cprboot on SPARC, which reloads kernel image)
672 670 * and CPR_TORAM (restart via reset into existing kernel image)
673 671 * cpus are not suspended and restored in the SPARC case, since it
674 672 * is necessary to restart the cpus and pause them before restoring
675 673 * the OBP image
676 674 */
677 675
678 676 #if defined(__x86)
679 677
680 678 /* pause aux cpus */
681 679 PMD(PMD_SX, ("pause aux cpus\n"))
682 680
683 681 cpr_set_substate(C_ST_MP_PAUSED);
684 682
685 683 if ((rc = cpr_suspend_cpus()) != 0)
686 684 return (rc);
687 685 #endif
688 686
689 687 PMD(PMD_SX, ("cpr_suspend: stop intr\n"))
690 688 i_cpr_stop_intr();
691 689 CPR_DEBUG(CPR_DEBUG1, "interrupt is stopped\n");
692 690
693 691 /*
694 692 * Since we will now disable the mechanism that causes prom_printfs
695 693 * to power up (if needed) the console fb/monitor, we assert that
696 694 * it must be up now.
697 695 */
698 696 ASSERT(pm_cfb_is_up());
699 697 PMD(PMD_SX, ("cpr_suspend: prom suspend prepost\n"))
700 698 prom_suspend_prepost();
701 699
702 700 #if defined(__sparc)
703 701 /*
704 702 * getting ready to write ourself out, flush the register
705 703 * windows to make sure that our stack is good when we
706 704 * come back on the resume side.
707 705 */
708 706 flush_windows();
709 707 #endif
710 708
711 709 /*
712 710 * For S3, we're done
713 711 */
714 712 if (sleeptype == CPR_TORAM) {
715 713 PMD(PMD_SX, ("cpr_suspend rets %x\n", rc))
716 714 cpr_set_substate(C_ST_NODUMP);
717 715 return (rc);
718 716 }
719 717 #if defined(__sparc)
720 718 /*
721 719 * FATAL: NO MORE MEMORY ALLOCATION ALLOWED AFTER THIS POINT!!!
722 720 *
723 721 * The system is quiesced at this point, we are ready to either dump
724 722 * to the state file for a extended sleep or a simple shutdown for
725 723 * systems with non-volatile memory.
726 724 */
727 725
728 726 /*
729 727 * special handling for reusable:
730 728 */
731 729 if (cpr_reusable_mode) {
732 730 cpr_set_substate(C_ST_SETPROPS_1);
733 731 if (nverr = cpr_set_properties(1))
734 732 return (nverr);
735 733 }
736 734
737 735 cpr_set_substate(C_ST_DUMP);
738 736 rc = cpr_dump(C_VP);
739 737
740 738 /*
741 739 * if any error occurred during dump, more
742 740 * special handling for reusable:
743 741 */
744 742 if (rc && cpr_reusable_mode) {
745 743 cpr_set_substate(C_ST_SETPROPS_0);
746 744 if (nverr = cpr_set_properties(0))
747 745 return (nverr);
748 746 }
749 747
750 748 if (rc == ENOSPC) {
751 749 cpr_set_substate(C_ST_DUMP_NOSPC);
752 750 (void) cpr_resume(sleeptype);
753 751 goto alloc_statefile;
754 752 } else if (rc == 0) {
755 753 if (cpr_reusable_mode) {
756 754 cpr_set_substate(C_ST_REUSABLE);
757 755 longjmp(&ttolwp(curthread)->lwp_qsav);
758 756 } else
759 757 rc = cpr_set_properties(1);
760 758 }
761 759 #endif
762 760 PMD(PMD_SX, ("cpr_suspend: return %d\n", rc))
763 761 return (rc);
764 762 }
765 763
766 764 void
767 765 cpr_resume_cpus(void)
768 766 {
769 767 /*
770 768 * this is a cut down version of start_other_cpus()
771 769 * just do the initialization to wake the other cpus
772 770 */
773 771
774 772 #if defined(__x86)
775 773 /*
776 774 * Initialize our syscall handlers
777 775 */
778 776 init_cpu_syscall(CPU);
779 777
780 778 #endif
781 779
782 780 i_cpr_pre_resume_cpus();
783 781
784 782 /*
↓ open down ↓ |
354 lines elided |
↑ open up ↑ |
785 783 * Restart the paused cpus
786 784 */
787 785 mutex_enter(&cpu_lock);
788 786 start_cpus();
789 787 mutex_exit(&cpu_lock);
790 788
791 789 i_cpr_post_resume_cpus();
792 790
793 791 mutex_enter(&cpu_lock);
794 792 /*
795 - * Restore this cpu to use the regular cpu_pause(), so that
796 - * online and offline will work correctly
797 - */
798 - cpu_pause_func = NULL;
799 -
800 - /*
801 793 * clear the affinity set in cpr_suspend_cpus()
802 794 */
803 795 affinity_clear();
804 796
805 797 /*
806 798 * offline all the cpus that were brought online during suspend
807 799 */
808 800 cpr_restore_offline();
809 801
810 802 mutex_exit(&cpu_lock);
811 803 }
812 804
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
813 805 void
814 806 cpr_unpause_cpus(void)
815 807 {
816 808 /*
817 809 * Now restore the system back to what it was before we suspended
818 810 */
819 811
820 812 PMD(PMD_SX, ("cpr_unpause_cpus: restoring system\n"))
821 813
822 814 mutex_enter(&cpu_lock);
823 -
824 - /*
825 - * Restore this cpu to use the regular cpu_pause(), so that
826 - * online and offline will work correctly
827 - */
828 - cpu_pause_func = NULL;
829 -
830 815 /*
831 816 * Restart the paused cpus
832 817 */
833 818 start_cpus();
834 819
835 820 /*
836 821 * clear the affinity set in cpr_suspend_cpus()
837 822 */
838 823 affinity_clear();
839 824
840 825 /*
841 826 * offline all the cpus that were brought online during suspend
842 827 */
843 828 cpr_restore_offline();
844 829
845 830 mutex_exit(&cpu_lock);
846 831 }
847 832
848 833 /*
849 834 * Bring the system back up from a checkpoint, at this point
850 835 * the VM has been minimally restored by boot, the following
851 836 * are executed sequentially:
852 837 *
853 838 * - machdep setup and enable interrupts (mp startup if it's mp)
854 839 * - resume all devices
855 840 * - restart daemons
856 841 * - put all threads back on run queue
857 842 */
858 843 static int
859 844 cpr_resume(int sleeptype)
860 845 {
861 846 cpr_time_t pwron_tv, *ctp;
862 847 char *str;
863 848 int rc = 0;
864 849
865 850 /*
866 851 * The following switch is used to resume the system
867 852 * that was suspended to a different level.
868 853 */
869 854 CPR_DEBUG(CPR_DEBUG1, "\nEntering cpr_resume...\n");
870 855 PMD(PMD_SX, ("cpr_resume %x\n", sleeptype))
871 856
872 857 /*
873 858 * Note:
874 859 *
875 860 * The rollback labels rb_xyz do not represent the cpr resume
876 861 * state when event 'xyz' has happened. Instead they represent
877 862 * the state during cpr suspend when event 'xyz' was being
878 863 * entered (and where cpr suspend failed). The actual call that
879 864 * failed may also need to be partially rolled back, since they
880 865 * aren't atomic in most cases. In other words, rb_xyz means
881 866 * "roll back all cpr suspend events that happened before 'xyz',
882 867 * and the one that caused the failure, if necessary."
883 868 */
884 869 switch (CPR->c_substate) {
885 870 #if defined(__sparc)
886 871 case C_ST_DUMP:
887 872 /*
888 873 * This is most likely a full-fledged cpr_resume after
889 874 * a complete and successful cpr suspend. Just roll back
890 875 * everything.
891 876 */
892 877 ASSERT(sleeptype == CPR_TODISK);
893 878 break;
894 879
895 880 case C_ST_REUSABLE:
896 881 case C_ST_DUMP_NOSPC:
897 882 case C_ST_SETPROPS_0:
898 883 case C_ST_SETPROPS_1:
899 884 /*
900 885 * C_ST_REUSABLE and C_ST_DUMP_NOSPC are the only two
901 886 * special switch cases here. The other two do not have
902 887 * any state change during cpr_suspend() that needs to
903 888 * be rolled back. But these are exit points from
904 889 * cpr_suspend, so theoretically (or in the future), it
905 890 * is possible that a need for roll back of a state
906 891 * change arises between these exit points.
907 892 */
908 893 ASSERT(sleeptype == CPR_TODISK);
909 894 goto rb_dump;
910 895 #endif
911 896
912 897 case C_ST_NODUMP:
913 898 PMD(PMD_SX, ("cpr_resume: NODUMP\n"))
914 899 goto rb_nodump;
915 900
916 901 case C_ST_STOP_KERNEL_THREADS:
917 902 PMD(PMD_SX, ("cpr_resume: STOP_KERNEL_THREADS\n"))
918 903 goto rb_stop_kernel_threads;
919 904
920 905 case C_ST_SUSPEND_DEVICES:
921 906 PMD(PMD_SX, ("cpr_resume: SUSPEND_DEVICES\n"))
922 907 goto rb_suspend_devices;
923 908
924 909 #if defined(__sparc)
925 910 case C_ST_STATEF_ALLOC:
926 911 ASSERT(sleeptype == CPR_TODISK);
927 912 goto rb_statef_alloc;
928 913
929 914 case C_ST_DISABLE_UFS_LOGGING:
930 915 ASSERT(sleeptype == CPR_TODISK);
931 916 goto rb_disable_ufs_logging;
932 917 #endif
933 918
934 919 case C_ST_PM_REATTACH_NOINVOL:
935 920 PMD(PMD_SX, ("cpr_resume: REATTACH_NOINVOL\n"))
936 921 goto rb_pm_reattach_noinvol;
937 922
938 923 case C_ST_STOP_USER_THREADS:
939 924 PMD(PMD_SX, ("cpr_resume: STOP_USER_THREADS\n"))
940 925 goto rb_stop_user_threads;
941 926
942 927 #if defined(__sparc)
943 928 case C_ST_MP_OFFLINE:
944 929 PMD(PMD_SX, ("cpr_resume: MP_OFFLINE\n"))
945 930 goto rb_mp_offline;
946 931 #endif
947 932
948 933 #if defined(__x86)
949 934 case C_ST_MP_PAUSED:
950 935 PMD(PMD_SX, ("cpr_resume: MP_PAUSED\n"))
951 936 goto rb_mp_paused;
952 937 #endif
953 938
954 939
955 940 default:
956 941 PMD(PMD_SX, ("cpr_resume: others\n"))
957 942 goto rb_others;
958 943 }
959 944
960 945 rb_all:
961 946 /*
962 947 * perform platform-dependent initialization
963 948 */
964 949 if (cpr_suspend_succeeded)
965 950 i_cpr_machdep_setup();
966 951
967 952 /*
968 953 * system did not really go down if we jump here
969 954 */
970 955 rb_dump:
971 956 /*
972 957 * IMPORTANT: SENSITIVE RESUME SEQUENCE
973 958 *
974 959 * DO NOT ADD ANY INITIALIZATION STEP BEFORE THIS POINT!!
975 960 */
976 961 rb_nodump:
977 962 /*
978 963 * If we did suspend to RAM, we didn't generate a dump
979 964 */
980 965 PMD(PMD_SX, ("cpr_resume: CPR DMA callback\n"))
981 966 (void) callb_execute_class(CB_CL_CPR_DMA, CB_CODE_CPR_RESUME);
982 967 if (cpr_suspend_succeeded) {
983 968 PMD(PMD_SX, ("cpr_resume: CPR RPC callback\n"))
984 969 (void) callb_execute_class(CB_CL_CPR_RPC, CB_CODE_CPR_RESUME);
985 970 }
986 971
987 972 prom_resume_prepost();
988 973 #if !defined(__sparc)
989 974 /*
990 975 * Need to sync the software clock with the hardware clock.
991 976 * On Sparc, this occurs in the sparc-specific cbe. However
992 977 * on x86 this needs to be handled _before_ we bring other cpu's
993 978 * back online. So we call a resume function in timestamp.c
994 979 */
995 980 if (tsc_resume_in_cyclic == 0)
996 981 tsc_resume();
997 982
998 983 #endif
999 984
1000 985 #if defined(__sparc)
1001 986 if (cpr_suspend_succeeded && (boothowto & RB_DEBUG))
1002 987 kdi_dvec_cpr_restart();
1003 988 #endif
1004 989
1005 990
1006 991 #if defined(__x86)
1007 992 rb_mp_paused:
1008 993 PT(PT_RMPO);
1009 994 PMD(PMD_SX, ("resume aux cpus\n"))
1010 995
1011 996 if (cpr_suspend_succeeded) {
1012 997 cpr_resume_cpus();
1013 998 } else {
1014 999 cpr_unpause_cpus();
1015 1000 }
1016 1001 #endif
1017 1002
1018 1003 /*
1019 1004 * let the tmp callout catch up.
1020 1005 */
1021 1006 PMD(PMD_SX, ("cpr_resume: CPR CALLOUT callback\n"))
1022 1007 (void) callb_execute_class(CB_CL_CPR_CALLOUT, CB_CODE_CPR_RESUME);
1023 1008
1024 1009 i_cpr_enable_intr();
1025 1010
1026 1011 mutex_enter(&cpu_lock);
1027 1012 PMD(PMD_SX, ("cpr_resume: cyclic resume\n"))
1028 1013 cyclic_resume();
1029 1014 mutex_exit(&cpu_lock);
1030 1015
1031 1016 PMD(PMD_SX, ("cpr_resume: handle xc\n"))
1032 1017 i_cpr_handle_xc(0); /* turn it off to allow xc assertion */
1033 1018
1034 1019 PMD(PMD_SX, ("cpr_resume: CPR POST KERNEL callback\n"))
1035 1020 (void) callb_execute_class(CB_CL_CPR_POST_KERNEL, CB_CODE_CPR_RESUME);
1036 1021
1037 1022 /*
1038 1023 * statistics gathering
1039 1024 */
1040 1025 if (cpr_suspend_succeeded) {
1041 1026 /*
1042 1027 * Prevent false alarm in tod_validate() due to tod
1043 1028 * value change between suspend and resume
1044 1029 */
1045 1030 cpr_tod_status_set(TOD_CPR_RESUME_DONE);
1046 1031
1047 1032 cpr_convert_promtime(&pwron_tv);
1048 1033
1049 1034 ctp = &cpr_term.tm_shutdown;
1050 1035 if (sleeptype == CPR_TODISK)
1051 1036 CPR_STAT_EVENT_END_TMZ(" write statefile", ctp);
1052 1037 CPR_STAT_EVENT_END_TMZ("Suspend Total", ctp);
1053 1038
1054 1039 CPR_STAT_EVENT_START_TMZ("Resume Total", &pwron_tv);
1055 1040
1056 1041 str = " prom time";
1057 1042 CPR_STAT_EVENT_START_TMZ(str, &pwron_tv);
1058 1043 ctp = &cpr_term.tm_cprboot_start;
1059 1044 CPR_STAT_EVENT_END_TMZ(str, ctp);
1060 1045
1061 1046 str = " read statefile";
1062 1047 CPR_STAT_EVENT_START_TMZ(str, ctp);
1063 1048 ctp = &cpr_term.tm_cprboot_end;
1064 1049 CPR_STAT_EVENT_END_TMZ(str, ctp);
1065 1050 }
1066 1051
1067 1052 rb_stop_kernel_threads:
1068 1053 /*
1069 1054 * Put all threads back to where they belong; get the kernel
1070 1055 * daemons straightened up too. Note that the callback table
1071 1056 * locked during cpr_stop_kernel_threads() is released only
1072 1057 * in cpr_start_kernel_threads(). Ensure modunloading is
1073 1058 * disabled before starting kernel threads, we don't want
1074 1059 * modunload thread to start changing device tree underneath.
1075 1060 */
1076 1061 PMD(PMD_SX, ("cpr_resume: modunload disable\n"))
1077 1062 modunload_disable();
1078 1063 PMD(PMD_SX, ("cpr_resume: start kernel threads\n"))
1079 1064 cpr_start_kernel_threads();
1080 1065
1081 1066 rb_suspend_devices:
1082 1067 CPR_DEBUG(CPR_DEBUG1, "resuming devices...");
1083 1068 CPR_STAT_EVENT_START(" start drivers");
1084 1069
1085 1070 PMD(PMD_SX,
1086 1071 ("cpr_resume: rb_suspend_devices: cpr_resume_uniproc = %d\n",
↓ open down ↓ |
247 lines elided |
↑ open up ↑ |
1087 1072 cpr_resume_uniproc))
1088 1073
1089 1074 #if defined(__x86)
1090 1075 /*
1091 1076 * If cpr_resume_uniproc is set, then pause all the other cpus
1092 1077 * apart from the current cpu, so that broken drivers that think
1093 1078 * that they are on a uniprocessor machine will resume
1094 1079 */
1095 1080 if (cpr_resume_uniproc) {
1096 1081 mutex_enter(&cpu_lock);
1097 - pause_cpus(NULL);
1082 + pause_cpus(NULL, NULL);
1098 1083 mutex_exit(&cpu_lock);
1099 1084 }
1100 1085 #endif
1101 1086
1102 1087 /*
1103 1088 * The policy here is to continue resume everything we can if we did
1104 1089 * not successfully finish suspend; and panic if we are coming back
1105 1090 * from a fully suspended system.
1106 1091 */
1107 1092 PMD(PMD_SX, ("cpr_resume: resume devices\n"))
1108 1093 rc = cpr_resume_devices(ddi_root_node(), 0);
1109 1094
1110 1095 cpr_sae(0);
1111 1096
1112 1097 str = "Failed to resume one or more devices.";
1113 1098
1114 1099 if (rc) {
1115 1100 if (CPR->c_substate == C_ST_DUMP ||
1116 1101 (sleeptype == CPR_TORAM &&
1117 1102 CPR->c_substate == C_ST_NODUMP)) {
1118 1103 if (cpr_test_point == FORCE_SUSPEND_TO_RAM) {
1119 1104 PMD(PMD_SX, ("cpr_resume: resume device "
1120 1105 "warn\n"))
1121 1106 cpr_err(CE_WARN, str);
1122 1107 } else {
1123 1108 PMD(PMD_SX, ("cpr_resume: resume device "
1124 1109 "panic\n"))
1125 1110 cpr_err(CE_PANIC, str);
1126 1111 }
1127 1112 } else {
1128 1113 PMD(PMD_SX, ("cpr_resume: resume device warn\n"))
1129 1114 cpr_err(CE_WARN, str);
1130 1115 }
1131 1116 }
1132 1117
1133 1118 CPR_STAT_EVENT_END(" start drivers");
1134 1119 CPR_DEBUG(CPR_DEBUG1, "done\n");
1135 1120
1136 1121 #if defined(__x86)
1137 1122 /*
1138 1123 * If cpr_resume_uniproc is set, then unpause all the processors
1139 1124 * that were paused before resuming the drivers
1140 1125 */
1141 1126 if (cpr_resume_uniproc) {
1142 1127 mutex_enter(&cpu_lock);
1143 1128 start_cpus();
1144 1129 mutex_exit(&cpu_lock);
1145 1130 }
1146 1131 #endif
1147 1132
1148 1133 /*
1149 1134 * If we had disabled modunloading in this cpr resume cycle (i.e. we
1150 1135 * resumed from a state earlier than C_ST_SUSPEND_DEVICES), re-enable
1151 1136 * modunloading now.
1152 1137 */
1153 1138 if (CPR->c_substate != C_ST_SUSPEND_DEVICES) {
1154 1139 PMD(PMD_SX, ("cpr_resume: modload enable\n"))
1155 1140 modunload_enable();
1156 1141 }
1157 1142
1158 1143 /*
1159 1144 * Hooks needed by lock manager prior to resuming.
1160 1145 * Refer to code for more comments.
1161 1146 */
1162 1147 PMD(PMD_SX, ("cpr_resume: lock mgr\n"))
1163 1148 cpr_lock_mgr(lm_cprresume);
1164 1149
1165 1150 #if defined(__sparc)
1166 1151 /*
1167 1152 * This is a partial (half) resume during cpr suspend, we
1168 1153 * haven't yet given up on the suspend. On return from here,
1169 1154 * cpr_suspend() will try to reallocate and retry the suspend.
1170 1155 */
1171 1156 if (CPR->c_substate == C_ST_DUMP_NOSPC) {
1172 1157 return (0);
1173 1158 }
1174 1159
1175 1160 if (sleeptype == CPR_TODISK) {
1176 1161 rb_statef_alloc:
1177 1162 cpr_statef_close();
1178 1163
1179 1164 rb_disable_ufs_logging:
1180 1165 /*
1181 1166 * if ufs logging was disabled, re-enable
1182 1167 */
1183 1168 (void) cpr_ufs_logging(1);
1184 1169 }
1185 1170 #endif
1186 1171
1187 1172 rb_pm_reattach_noinvol:
1188 1173 /*
1189 1174 * When pm_reattach_noinvol() succeeds, modunload_thread will
1190 1175 * remain disabled until after cpr suspend passes the
1191 1176 * C_ST_STOP_KERNEL_THREADS state. If any failure happens before
1192 1177 * cpr suspend reaches this state, we'll need to enable modunload
1193 1178 * thread during rollback.
1194 1179 */
1195 1180 if (CPR->c_substate == C_ST_DISABLE_UFS_LOGGING ||
1196 1181 CPR->c_substate == C_ST_STATEF_ALLOC ||
1197 1182 CPR->c_substate == C_ST_SUSPEND_DEVICES ||
1198 1183 CPR->c_substate == C_ST_STOP_KERNEL_THREADS) {
1199 1184 PMD(PMD_SX, ("cpr_resume: reattach noinvol fini\n"))
1200 1185 pm_reattach_noinvol_fini();
1201 1186 }
1202 1187
1203 1188 PMD(PMD_SX, ("cpr_resume: CPR POST USER callback\n"))
1204 1189 (void) callb_execute_class(CB_CL_CPR_POST_USER, CB_CODE_CPR_RESUME);
1205 1190 PMD(PMD_SX, ("cpr_resume: CPR PROMPRINTF callback\n"))
1206 1191 (void) callb_execute_class(CB_CL_CPR_PROMPRINTF, CB_CODE_CPR_RESUME);
1207 1192
1208 1193 PMD(PMD_SX, ("cpr_resume: restore direct levels\n"))
1209 1194 pm_restore_direct_levels();
1210 1195
1211 1196 rb_stop_user_threads:
1212 1197 CPR_DEBUG(CPR_DEBUG1, "starting user threads...");
1213 1198 PMD(PMD_SX, ("cpr_resume: starting user threads\n"))
1214 1199 cpr_start_user_threads();
1215 1200 CPR_DEBUG(CPR_DEBUG1, "done\n");
1216 1201 /*
1217 1202 * Ask Xorg to resume the frame buffer, and wait for it to happen
1218 1203 */
1219 1204 mutex_enter(&srn_clone_lock);
1220 1205 if (srn_signal) {
1221 1206 PMD(PMD_SX, ("cpr_suspend: (*srn_signal)(..., "
1222 1207 "SRN_NORMAL_RESUME)\n"))
1223 1208 srn_inuse = 1; /* because (*srn_signal) cv_waits */
1224 1209 (*srn_signal)(SRN_TYPE_APM, SRN_NORMAL_RESUME);
1225 1210 srn_inuse = 0;
1226 1211 } else {
1227 1212 PMD(PMD_SX, ("cpr_suspend: srn_signal NULL\n"))
1228 1213 }
1229 1214 mutex_exit(&srn_clone_lock);
1230 1215
1231 1216 #if defined(__sparc)
1232 1217 rb_mp_offline:
1233 1218 if (cpr_mp_online())
1234 1219 cpr_err(CE_WARN, "Failed to online all the processors.");
1235 1220 #endif
1236 1221
1237 1222 rb_others:
1238 1223 PMD(PMD_SX, ("cpr_resume: dep thread\n"))
1239 1224 pm_dispatch_to_dep_thread(PM_DEP_WK_CPR_RESUME, NULL, NULL,
1240 1225 PM_DEP_WAIT, NULL, 0);
1241 1226
1242 1227 PMD(PMD_SX, ("cpr_resume: CPR PM callback\n"))
1243 1228 (void) callb_execute_class(CB_CL_CPR_PM, CB_CODE_CPR_RESUME);
1244 1229
1245 1230 if (cpr_suspend_succeeded) {
1246 1231 cpr_stat_record_events();
1247 1232 }
1248 1233
1249 1234 #if defined(__sparc)
1250 1235 if (sleeptype == CPR_TODISK && !cpr_reusable_mode)
1251 1236 cpr_clear_definfo();
1252 1237 #endif
1253 1238
1254 1239 i_cpr_free_cpus();
1255 1240 CPR_DEBUG(CPR_DEBUG1, "Sending SIGTHAW...");
1256 1241 PMD(PMD_SX, ("cpr_resume: SIGTHAW\n"))
1257 1242 cpr_signal_user(SIGTHAW);
1258 1243 CPR_DEBUG(CPR_DEBUG1, "done\n");
1259 1244
1260 1245 CPR_STAT_EVENT_END("Resume Total");
1261 1246
1262 1247 CPR_STAT_EVENT_START_TMZ("WHOLE CYCLE", &wholecycle_tv);
1263 1248 CPR_STAT_EVENT_END("WHOLE CYCLE");
1264 1249
1265 1250 if (cpr_debug & CPR_DEBUG1)
1266 1251 cmn_err(CE_CONT, "\nThe system is back where you left!\n");
1267 1252
1268 1253 CPR_STAT_EVENT_START("POST CPR DELAY");
1269 1254
1270 1255 #ifdef CPR_STAT
1271 1256 ctp = &cpr_term.tm_shutdown;
1272 1257 CPR_STAT_EVENT_START_TMZ("PWROFF TIME", ctp);
1273 1258 CPR_STAT_EVENT_END_TMZ("PWROFF TIME", &pwron_tv);
1274 1259
1275 1260 CPR_STAT_EVENT_PRINT();
1276 1261 #endif /* CPR_STAT */
1277 1262
1278 1263 PMD(PMD_SX, ("cpr_resume returns %x\n", rc))
1279 1264 return (rc);
1280 1265 }
1281 1266
1282 1267 static void
1283 1268 cpr_suspend_init(int sleeptype)
1284 1269 {
1285 1270 cpr_time_t *ctp;
1286 1271
1287 1272 cpr_stat_init();
1288 1273
1289 1274 /*
1290 1275 * If cpr_suspend() failed before cpr_dump() gets a chance
1291 1276 * to reinitialize the terminator of the statefile,
1292 1277 * the values of the old terminator will still linger around.
1293 1278 * Since the terminator contains information that we need to
1294 1279 * decide whether suspend succeeded or not, we need to
1295 1280 * reinitialize it as early as possible.
1296 1281 */
1297 1282 cpr_term.real_statef_size = 0;
1298 1283 ctp = &cpr_term.tm_shutdown;
1299 1284 bzero(ctp, sizeof (*ctp));
1300 1285 ctp = &cpr_term.tm_cprboot_start;
1301 1286 bzero(ctp, sizeof (*ctp));
1302 1287 ctp = &cpr_term.tm_cprboot_end;
1303 1288 bzero(ctp, sizeof (*ctp));
1304 1289
1305 1290 if (sleeptype == CPR_TODISK) {
1306 1291 /*
1307 1292 * Lookup the physical address of our thread structure.
1308 1293 * This should never be invalid and the entire thread structure
1309 1294 * is expected to reside within the same pfn.
1310 1295 */
1311 1296 curthreadpfn = hat_getpfnum(kas.a_hat, (caddr_t)curthread);
1312 1297 ASSERT(curthreadpfn != PFN_INVALID);
1313 1298 ASSERT(curthreadpfn == hat_getpfnum(kas.a_hat,
1314 1299 (caddr_t)curthread + sizeof (kthread_t) - 1));
1315 1300 }
1316 1301
1317 1302 cpr_suspend_succeeded = 0;
1318 1303 }
1319 1304
1320 1305 /*
1321 1306 * bring all the offline cpus online
1322 1307 */
1323 1308 static int
1324 1309 cpr_all_online(void)
1325 1310 {
1326 1311 int rc = 0;
1327 1312
1328 1313 #ifdef __sparc
1329 1314 /*
1330 1315 * do nothing
1331 1316 */
1332 1317 #else
1333 1318
1334 1319 cpu_t *cp;
1335 1320
1336 1321 ASSERT(MUTEX_HELD(&cpu_lock));
1337 1322
1338 1323 cp = cpu_list;
1339 1324 do {
1340 1325 cp->cpu_cpr_flags &= ~CPU_CPR_ONLINE;
1341 1326 if (!CPU_ACTIVE(cp)) {
1342 1327 if ((rc = cpu_online(cp)) != 0)
1343 1328 break;
1344 1329 CPU_SET_CPR_FLAGS(cp, CPU_CPR_ONLINE);
1345 1330 }
1346 1331 } while ((cp = cp->cpu_next) != cpu_list);
1347 1332
1348 1333 if (rc) {
1349 1334 /*
1350 1335 * an online operation failed so offline the cpus
1351 1336 * that were onlined above to restore the system
1352 1337 * to its original state
1353 1338 */
1354 1339 cpr_restore_offline();
1355 1340 }
1356 1341 #endif
1357 1342 return (rc);
1358 1343 }
1359 1344
1360 1345 /*
1361 1346 * offline all the cpus that were brought online by cpr_all_online()
1362 1347 */
1363 1348 static void
1364 1349 cpr_restore_offline(void)
1365 1350 {
1366 1351
1367 1352 #ifdef __sparc
1368 1353 /*
1369 1354 * do nothing
1370 1355 */
1371 1356 #else
1372 1357
1373 1358 cpu_t *cp;
1374 1359 int rc = 0;
1375 1360
1376 1361 ASSERT(MUTEX_HELD(&cpu_lock));
1377 1362
1378 1363 cp = cpu_list;
1379 1364 do {
1380 1365 if (CPU_CPR_IS_ONLINE(cp)) {
1381 1366 rc = cpu_offline(cp, 0);
1382 1367 /*
1383 1368 * this offline should work, since the cpu was
1384 1369 * offline originally and was successfully onlined
1385 1370 * by cpr_all_online()
1386 1371 */
1387 1372 ASSERT(rc == 0);
1388 1373 cp->cpu_cpr_flags &= ~CPU_CPR_ONLINE;
1389 1374 }
1390 1375 } while ((cp = cp->cpu_next) != cpu_list);
1391 1376
1392 1377 #endif
1393 1378
1394 1379 }
↓ open down ↓ |
287 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX