void execute_string(char *string) { char buf[RESULT_BUF_SIZE]; int n; ec_post_string(string); int res = 7; //means that we have to flush the output. while (res == 7) { res = ec_resume(); SKB_DEBUG("\nres = %d\n", res); //give back the result and the error messages. //in case there is no message, a '.' is still returned n = ec_queue_read(1, buf, RESULT_BUF_SIZE); if ((n >= 0) && (n < RESULT_BUF_SIZE)) { buf[n] = 0; } SKB_DEBUG("eclipse returned: %s with length %d.\n", buf, n); n = ec_queue_read(2, buf, RESULT_BUF_SIZE); if ((n >= 0) && (n < RESULT_BUF_SIZE)) { buf[n] = 0; } SKB_DEBUG("eclipse error returned: %s with length %d.\n", buf, n); } }
/* * Top level routine to direct suspend/resume of a domain. */ void xen_suspend_domain(void) { extern void rtcsync(void); extern hrtime_t hres_last_tick; mfn_t start_info_mfn; ulong_t flags; pfn_t pfn; int i; /* * Check that we are happy to suspend on this hypervisor. */ if (xen_hypervisor_supports_solaris(XEN_SUSPEND_CHECK) == 0) { cpr_err(CE_WARN, "Cannot suspend on this hypervisor " "version: v%lu.%lu%s, need at least version v3.0.4 or " "-xvm based hypervisor", XENVER_CURRENT(xv_major), XENVER_CURRENT(xv_minor), XENVER_CURRENT(xv_ver)); return; } /* * XXPV - Are we definitely OK to suspend by the time we've connected * the handler? */ cpr_err(CE_NOTE, "Domain suspending for save/migrate"); SUSPEND_DEBUG("xen_suspend_domain\n"); /* * suspend interrupts and devices * XXPV - we use suspend/resume for both save/restore domains (like sun * cpr) and for migration. Would be nice to know the difference if * possible. For save/restore where down time may be a long time, we * may want to do more of the things that cpr does. (i.e. notify user * processes, shrink memory footprint for faster restore, etc.) */ xen_suspend_devices(); SUSPEND_DEBUG("xenbus_suspend\n"); xenbus_suspend(); pfn = hat_getpfnum(kas.a_hat, (caddr_t)xen_info); start_info_mfn = pfn_to_mfn(pfn); /* * XXPV: cpu hotplug can hold this under a xenbus watch. Are we safe * wrt xenbus being suspended here? */ mutex_enter(&cpu_lock); /* * Suspend must be done on vcpu 0, as no context for other CPUs is * saved. * * XXPV - add to taskq API ? */ thread_affinity_set(curthread, 0); kpreempt_disable(); SUSPEND_DEBUG("xen_start_migrate\n"); xen_start_migrate(); if (ncpus > 1) suspend_cpus(); /* * We can grab the ec_lock as it's a spinlock with a high SPL. Hence * any holder would have dropped it to get through suspend_cpus(). */ mutex_enter(&ec_lock); /* * From here on in, we can't take locks. */ SUSPEND_DEBUG("ec_suspend\n"); ec_suspend(); SUSPEND_DEBUG("gnttab_suspend\n"); gnttab_suspend(); flags = intr_clear(); xpv_time_suspend(); /* * Currently, the hypervisor incorrectly fails to bring back * powered-down VCPUs. Thus we need to record any powered-down VCPUs * to prevent any attempts to operate on them. But we have to do this * *after* the very first time we do ec_suspend(). */ for (i = 1; i < ncpus; i++) { if (cpu[i] == NULL) continue; if (cpu_get_state(cpu[i]) == P_POWEROFF) CPUSET_ATOMIC_ADD(cpu_suspend_lost_set, i); } /* * The dom0 save/migrate code doesn't automatically translate * these into PFNs, but expects them to be, so we do it here. * We don't use mfn_to_pfn() because so many OS services have * been disabled at this point. */ xen_info->store_mfn = mfn_to_pfn_mapping[xen_info->store_mfn]; xen_info->console.domU.mfn = mfn_to_pfn_mapping[xen_info->console.domU.mfn]; if (CPU->cpu_m.mcpu_vcpu_info->evtchn_upcall_mask == 0) { prom_printf("xen_suspend_domain(): " "CPU->cpu_m.mcpu_vcpu_info->evtchn_upcall_mask not set\n"); (void) HYPERVISOR_shutdown(SHUTDOWN_crash); } if (HYPERVISOR_update_va_mapping((uintptr_t)HYPERVISOR_shared_info, 0, UVMF_INVLPG)) { prom_printf("xen_suspend_domain(): " "HYPERVISOR_update_va_mapping() failed\n"); (void) HYPERVISOR_shutdown(SHUTDOWN_crash); } SUSPEND_DEBUG("HYPERVISOR_suspend\n"); /* * At this point we suspend and sometime later resume. */ if (HYPERVISOR_suspend(start_info_mfn)) { prom_printf("xen_suspend_domain(): " "HYPERVISOR_suspend() failed\n"); (void) HYPERVISOR_shutdown(SHUTDOWN_crash); } /* * Point HYPERVISOR_shared_info to its new value. */ if (HYPERVISOR_update_va_mapping((uintptr_t)HYPERVISOR_shared_info, xen_info->shared_info | PT_NOCONSIST | PT_VALID | PT_WRITABLE, UVMF_INVLPG)) (void) HYPERVISOR_shutdown(SHUTDOWN_crash); if (xen_info->nr_pages != mfn_count) { prom_printf("xen_suspend_domain(): number of pages" " changed, was 0x%lx, now 0x%lx\n", mfn_count, xen_info->nr_pages); (void) HYPERVISOR_shutdown(SHUTDOWN_crash); } xpv_time_resume(); cached_max_mfn = 0; SUSPEND_DEBUG("gnttab_resume\n"); gnttab_resume(); /* XXPV: add a note that this must be lockless. */ SUSPEND_DEBUG("ec_resume\n"); ec_resume(); intr_restore(flags); if (ncpus > 1) resume_cpus(); mutex_exit(&ec_lock); xen_end_migrate(); mutex_exit(&cpu_lock); /* * Now we can take locks again. */ /* * Force the tick value used for tv_nsec in hres_tick() to be up to * date. rtcsync() will reset the hrestime value appropriately. */ hres_last_tick = xpv_gethrtime(); /* * XXPV: we need to have resumed the CPUs since this takes locks, but * can remote CPUs see bad state? Presumably yes. Should probably nest * taking of todlock inside of cpu_lock, or vice versa, then provide an * unlocked version. Probably need to call clkinitf to reset cpu freq * and re-calibrate if we migrated to a different speed cpu. Also need * to make a (re)init_cpu_info call to update processor info structs * and device tree info. That remains to be written at the moment. */ rtcsync(); rebuild_mfn_list(); SUSPEND_DEBUG("xenbus_resume\n"); xenbus_resume(); SUSPEND_DEBUG("xenbus_resume_devices\n"); xen_resume_devices(); thread_affinity_clear(curthread); kpreempt_enable(); SUSPEND_DEBUG("finished xen_suspend_domain\n"); /* * We have restarted our suspended domain, update the hypervisor * details. NB: This must be done at the end of this function, * since we need the domain to be completely resumed before * these functions will work correctly. */ xen_set_version(XENVER_CURRENT_IDX); /* * We can check and report a warning, but we don't stop the * process. */ if (xen_hypervisor_supports_solaris(XEN_SUSPEND_CHECK) == 0) cmn_err(CE_WARN, "Found hypervisor version: v%lu.%lu%s " "but need at least version v3.0.4", XENVER_CURRENT(xv_major), XENVER_CURRENT(xv_minor), XENVER_CURRENT(xv_ver)); cmn_err(CE_NOTE, "domain restore/migrate completed"); }
main(int argc, char **argv) { char * eclipsedir = (char *) 0; int c, new_argc, err; int init_flags = INIT_SHARED|INIT_PRIVATE|INIT_ENGINE|INIT_PROCESS; char * session, * nsrv_hostname; unsigned nsrv_port_number; uword size; /* * If stdio is not a tty, get rid of the console window. This is not ideal * since the window flashes up briefly, but no better solution yet. * (The correct way would be not to build eclipse.exe as a "console * application" and have a WinMain() instead of main(). But then we have * to do all the setup of stdin/out/err, argc/argv, environment etc * ourselves) */ if (!isatty(_fileno(stdin)) && !isatty(_fileno(stdout)) && !isatty(_fileno(stderr))) { FreeConsole(); } /* * collect information from the command line * remove some internally used arguments from the command line */ for (c = new_argc = 1; c < argc; ) { if (argv[c][0] == '-' && argv[c][2] == 0) /* single char opt */ { switch (argv[c][1]) { case 'a': /* -a <worker> <session> <nsrv_hostname> <nsrv_port_no> */ if (++c + 4 > argc) usage(argv[c-1]); ec_set_option_int(EC_OPTION_PARALLEL_WORKER, atoi(argv[c++])); session = argv[c++]; nsrv_hostname = argv[c++]; nsrv_port_number = atoi(argv[c++]); break; case 'c': /* -c <shared_map_file> */ if (++c + 1 > argc) usage(argv[c-1]); ec_set_option_ptr(EC_OPTION_MAPFILE, argv[c++]); ec_set_option_int(EC_OPTION_ALLOCATION, ALLOC_FIXED); init_flags &= ~INIT_SHARED; break; case 'm': /* -m <shared_map_file> */ if (++c + 1 > argc) usage(argv[c-1]); ec_set_option_ptr(EC_OPTION_MAPFILE, argv[c++]); ec_set_option_int(EC_OPTION_ALLOCATION, ALLOC_FIXED); break; case 'b': /* -b <bootfile> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c++]; /* shift */ break; case 'e': /* -e <goal> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c++]; /* shift */ break; case 'g': /* -g <size> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c]; /* shift */ size = sizearg(argv[c++]); ec_set_option_long(EC_OPTION_GLOBALSIZE, size); if (size < MIN_GLOBAL) { fprintf(stderr,"Global stack size out of range\n"); exit(-1); } break; case 'd': /* -d <n> */ /* delay worker startup by <n> seconds */ if (++c + 1 > argc) usage(argv[c-1]); Sleep(1000 * atoi(argv[c++])); break; case 'D': /* -D <eclipsedir> */ if (++c + 1 > argc) usage(argv[c-1]); eclipsedir = argv[c++]; break; case 'l': /* -l <size> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c]; /* shift */ size = sizearg(argv[c++]); ec_set_option_long(EC_OPTION_LOCALSIZE, size); if (size < MIN_LOCAL) { fprintf(stderr,"Local stack size out of range\n"); exit(-1); } break; case 'h': /* -h <size> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c]; /* shift */ size = sizearg(argv[c++]); ec_set_option_long(EC_OPTION_PRIVATESIZE, size); if (size < MIN_PRIVATE) { fprintf(stderr,"Private heap size out of range\n"); exit(-1); } break; case 's': /* -s <size> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c]; /* shift */ size = sizearg(argv[c++]); ec_set_option_long(EC_OPTION_SHAREDSIZE, size); if (size < MIN_SHARED) { fprintf(stderr,"Shared heap size out of range\n"); exit(-1); } break; case 'o': /* enable oracles */ c += 1; /* vm_options = ORACLES_ENABLED; */ break; case '-': /* -- give the rest to Prolog */ for (; c < argc; ) argv[new_argc++] = argv[c++]; break; default: /* unknown: error */ usage(argv[c]); break; } } else if (!strcmp(argv[c], "-debug_level")) { if (++c + 1 > argc) usage(argv[c-1]); ec_set_option_int(EC_OPTION_DEBUG_LEVEL, atoi(argv[c++])); } else /* raise error unless preceeded by a -- option */ { usage(argv[c]); } } /*---------------------------------------------------------------- * Entry point after longjmp(reset) *----------------------------------------------------------------*/ switch (setjmp(reset)) { case 0: /* raw boot or -r from above */ break; case 3: /* restore program state */ case 2: init_flags = REINIT_SHARED|INIT_ENGINE|INIT_PRIVATE; break; case 4: /* restore execution state */ init_flags = REINIT_SHARED|INIT_PRIVATE; break; case 1: /* reset after fatal error */ default: init_flags = INIT_ENGINE; switch (memory_corrupted++) { case 0: break; case 1: /* try to print a message */ memory_corrupted = 2; fprintf(stderr,"\n*** SEPIA Fatal error: memory corrupted\n"); /* fall to */ case 2: /* we couldn't even print the message */ exit(-1); } break; } /* * set up our own panic function which longjumps back to reset */ ec_set_option_ptr(EC_OPTION_PANIC, main_panic); ec_set_option_int(EC_OPTION_INIT, init_flags); ec_set_option_int(EC_OPTION_ARGC, new_argc); ec_set_option_ptr(EC_OPTION_ARGV, argv); if (eclipsedir) ec_set_option_ptr(EC_OPTION_ECLIPSEDIR, eclipsedir); ec_init(); ec_post_goal(ec_term(ec_did(":",2), ec_atom(ec_did("sepia_kernel",0)), ec_atom(ec_did("standalone_toplevel",0)))); do { err = ec_resume(); } while (err == PYIELD); ec_cleanup(); return err; }
int main(int argc, char **argv) { char bootfile_buf[MAX_PATH_LEN]; char * initfile = (char *) 0; char * eclipsedir = (char *) 0; int c, new_argc; pword goal, module; int err; int init_flags = INIT_SHARED|INIT_PRIVATE|INIT_ENGINE|INIT_PROCESS; unsigned startup_delay = 0; int vm_options = 0; char * session, * nsrv_hostname; unsigned nsrv_port_number; #ifdef PROFILE moncontrol(0); /* disable profiling by default */ #endif /* * collect information from the command line * remove some internally used arguments from the command line */ for (c = new_argc = 1; c < argc; ) { if (argv[c][0] == '-' && argv[c][2] == 0) /* single char opt */ { switch (argv[c][1]) { case 'a': /* -a <worker> <session> <nsrv_hostname> <nsrv_port_no> */ if (++c + 4 > argc) usage(argv[c-1]); ec_options.parallel_worker = atoi(argv[c++]); session = argv[c++]; nsrv_hostname = argv[c++]; nsrv_port_number = atoi(argv[c++]); break; case 'c': /* -c <shared_map_file> */ if (++c + 1 > argc) usage(argv[c-1]); ec_options.mapfile = argv[c++]; ec_options.allocation = ALLOC_FIXED; init_flags &= ~INIT_SHARED; break; case 'm': /* -m <shared_map_file> */ if (++c + 1 > argc) usage(argv[c-1]); ec_options.mapfile = argv[c++]; ec_options.allocation = ALLOC_FIXED; break; case 'b': /* -b <bootfile> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c++]; /* shift */ break; case 'e': /* -e <goal> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c++]; /* shift */ break; case 'g': /* -g <size> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c]; /* shift */ ec_options.globalsize = sizearg(argv[c++]); if (ec_options.globalsize < MIN_GLOBAL) { ec_bad_exit("ECLiPSe: Global stack size out of range."); } break; case 'd': /* -d <n> */ /* delay worker startup by <n> seconds */ if (++c + 1 > argc) usage(argv[c-1]); startup_delay = atoi(argv[c++]); if (startup_delay == 0) ec_options.io_option = OWN_IO; /* every worker has its own i/o */ else sleep(startup_delay); break; case 'D': /* -D <eclipsedir> */ if (++c + 1 > argc) usage(argv[c-1]); eclipsedir = argv[c++]; break; case 'l': /* -l <size> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c]; /* shift */ ec_options.localsize = sizearg(argv[c++]); if (ec_options.localsize < MIN_LOCAL) { ec_bad_exit("ECLiPSe: local stack size out of range."); } break; case 'h': /* -h <size> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c]; /* shift */ ec_options.privatesize = sizearg(argv[c++]); if (ec_options.privatesize < MIN_PRIVATE) { ec_bad_exit("ECLiPSe: Private heap size out of range."); } break; case 's': /* -s <size> */ argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-1]); argv[new_argc++] = argv[c]; /* shift */ ec_options.sharedsize = sizearg(argv[c++]); if (ec_options.sharedsize < MIN_SHARED) { ec_bad_exit("ECLiPSe: Shared heap size out of range."); } break; case 'o': /* enable oracles */ c += 1; vm_options = ORACLES_ENABLED; break; case 'p': argv[new_argc++] = argv[c]; /* shift */ if (++c + 1 > argc) usage(argv[c-2]); argv[new_argc++] = argv[c]; /* shift */ ec_options.option_p = atoi(argv[c++]); break; case '-': /* -- give the rest to Prolog */ for (; c < argc;) argv[new_argc++] = argv[c++]; break; default: /* unknown: error */ usage(argv[c]); break; } } else if (!strcmp(argv[c], "-debug_level")) { if (++c + 1 > argc) usage(argv[c-1]); ec_options.debug_level = atoi(argv[c++]); } else if (!strcmp(argv[c], "-layout")) { int lflags = 0; char *from = 0; char *to = 0; long increment = 0L; if (++c + 1 <= argc) lflags = (int) strtol(argv[c++], (char **) 0, 16); if (c + 1 <= argc) increment = strtol(argv[c++], (char **) 0, 16); if (c + 1 <= argc) from = (char *) strtol(argv[c++], (char **) 0, 16); if (c + 1 <= argc) to = (char *) strtol(argv[c++], (char **) 0, 16); if (ec_options.allocation == ALLOC_FIXED) mem_layout(); #ifdef HAVE_MMAP ec_layout(lflags, from, to, increment); #else ec_bad_exit("ECLiPSe: The -layout scan is not supported without\nmemory mapping."); #endif } else if (!strcmp(argv[c], "-norl")) { argv[new_argc++] = argv[c++]; /* shift */ ec_options.rl = 0; } else /* raise error unless preceeded by a -- option */ { usage(argv[c]); } } /*---------------------------------------------------------------- * Initialize private heap as early as possible * (must be before setup_mps()) *----------------------------------------------------------------*/ malloc_init(); irq_lock_init(delayed_break); /*---------------------------------------------------------------- * Init message passing system *----------------------------------------------------------------*/ if (ec_options.parallel_worker) { setup_mps(ec_options.parallel_worker, session, nsrv_hostname, nsrv_port_number, init_flags & INIT_SHARED); } /*---------------------------------------------------------------- * Make the connection to the shared heap, if any. * Because of mmap problems on some machines this should * happen AFTER initializing the message passing system. *----------------------------------------------------------------*/ mem_init(init_flags); /* depends on -c and -m options */ /*---------------------------------------------------------------- * Init parallel scheduler etc. *----------------------------------------------------------------*/ if (ec_options.parallel_worker) { parallel_init(init_flags); } /*---------------------------------------------------------------- * Init the low-level I/O stuff, ie the part which should * really not be done by eclipse itself... *----------------------------------------------------------------*/ /* char_io_init(); does not yet exist */ /*---------------------------------------------------------------- * Entry point after longjmp(reset) *----------------------------------------------------------------*/ switch (setjmp(reset)) { case 0: /* raw boot or -r from above */ break; case 3: /* restore program state */ case 2: init_flags = REINIT_SHARED|INIT_ENGINE|INIT_PRIVATE; break; case 4: /* restore execution state */ init_flags = REINIT_SHARED|INIT_PRIVATE; break; case 1: /* reset after fatal error */ default: if (!(GlobalFlags & HEAP_READY) || ec_options.parallel_worker) { (void) ec_cleanup(); exit(-1); } init_flags = INIT_ENGINE; switch (memory_corrupted++) { case 0: break; case 1: /* try to print a message */ memory_corrupted = 2; ec_bad_exit("ECLiPSe: Fatal error, memory corrupted."); /* fall to */ case 2: /* we couldn't even print the message */ exit(-1); } break; } /* * set up our own panic function which longjumps back to reset * To access command line through global variabes */ ec_options.user_panic = main_panic; ec_options.Argc = new_argc; ec_options.Argv = argv; ec_options.eclipse_home = (char *) 0; ec_options.init_flags = init_flags; if (eclipsedir) ec_options.eclipse_home = eclipsedir; /* * Init the global (shared) eclipse structures, dictionary, code... * Maybe load a saved state. * Note that we don't have an engine yet! */ eclipse_global_init(init_flags); /*---------------------------------------------------------------- * Setup the Prolog engine *----------------------------------------------------------------*/ /* * If we have a PROG_AND_DATA saved state (execution state saved) * we are finished and enter the emulator. */ if (!(init_flags & INIT_ENGINE)) { err = restart_emulc(); (void) ec_cleanup(); exit(err); } /* * Initialize the Prolog engine */ emu_init(init_flags, vm_options); /* * If we are not running an already booted eclipse, * compile $ECLIPSEDIR/lib/kernel.eco */ if (init_flags & INIT_SHARED) { char msg[1024]; initfile = strcat(strcpy(bootfile_buf, ec_eclipse_home), "/lib/kernel.eco"); if (ec_access(initfile, R_OK) < 0) { sprintf(msg, "ECLiPSe: Can't find boot file %s!\nPlease check the setting of your ECLIPSEDIR environment variable\nor use the -D <dir> command line option.", initfile); ec_bad_exit(msg); } err = eclipse_boot(initfile); if (err != PSUCCEED) { (void) ec_cleanup(); exit(err); } } if (init_flags & (INIT_SHARED|REINIT_SHARED)) GlobalFlags |= HEAP_READY; /* for the other workers */ goal = ec_term(ec_did("main",1), ec_long(init_flags & INIT_SHARED ? 0 : 1)); module.val.did = d_.kernel_sepia; module.tag.kernel = ModuleTag(d_.kernel_sepia); if (ec_options.parallel_worker <= 1) /* only or first worker */ { err = main_emulc_noexit(goal.val, goal.tag, module.val, module.tag); if (err == PYIELD) { memory_corrupted = 0; /* assume it's ok */ ec_post_goal(ec_term(ec_did(":",2), ec_atom(ec_did("sepia_kernel",0)), ec_atom(ec_did("standalone_toplevel",0)))); do { err = ec_resume(); } while (err == PYIELD); } } else { err = slave_emulc(); } ec_cleanup(); exit(err); /*NOTREACHED*/ }
/* * Top level routine to direct suspend/resume of a domain. */ void xen_suspend_domain(void) { extern void rtcsync(void); extern void ec_resume(void); extern kmutex_t ec_lock; struct xen_add_to_physmap xatp; ulong_t flags; int err; cmn_err(CE_NOTE, "Domain suspending for save/migrate"); SUSPEND_DEBUG("xen_suspend_domain\n"); /* * We only want to suspend the PV devices, since the emulated devices * are suspended by saving the emulated device state. The PV devices * are all children of the xpvd nexus device. So we search the * device tree for the xpvd node to use as the root of the tree to * be suspended. */ if (xpvd_dip == NULL) ddi_walk_devs(ddi_root_node(), check_xpvd, NULL); /* * suspend interrupts and devices */ if (xpvd_dip != NULL) (void) xen_suspend_devices(ddi_get_child(xpvd_dip)); else cmn_err(CE_WARN, "No PV devices found to suspend"); SUSPEND_DEBUG("xenbus_suspend\n"); xenbus_suspend(); mutex_enter(&cpu_lock); /* * Suspend on vcpu 0 */ thread_affinity_set(curthread, 0); kpreempt_disable(); if (ncpus > 1) pause_cpus(NULL, NULL); /* * We can grab the ec_lock as it's a spinlock with a high SPL. Hence * any holder would have dropped it to get through pause_cpus(). */ mutex_enter(&ec_lock); /* * From here on in, we can't take locks. */ flags = intr_clear(); SUSPEND_DEBUG("HYPERVISOR_suspend\n"); /* * At this point we suspend and sometime later resume. * Note that this call may return with an indication of a cancelled * for now no matter ehat the return we do a full resume of all * suspended drivers, etc. */ (void) HYPERVISOR_shutdown(SHUTDOWN_suspend); /* * Point HYPERVISOR_shared_info to the proper place. */ xatp.domid = DOMID_SELF; xatp.idx = 0; xatp.space = XENMAPSPACE_shared_info; xatp.gpfn = xen_shared_info_frame; if ((err = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp)) != 0) panic("Could not set shared_info page. error: %d", err); SUSPEND_DEBUG("gnttab_resume\n"); gnttab_resume(); SUSPEND_DEBUG("ec_resume\n"); ec_resume(); intr_restore(flags); if (ncpus > 1) start_cpus(); mutex_exit(&ec_lock); mutex_exit(&cpu_lock); /* * Now we can take locks again. */ rtcsync(); SUSPEND_DEBUG("xenbus_resume\n"); xenbus_resume(); SUSPEND_DEBUG("xen_resume_devices\n"); if (xpvd_dip != NULL) (void) xen_resume_devices(ddi_get_child(xpvd_dip), 0); thread_affinity_clear(curthread); kpreempt_enable(); SUSPEND_DEBUG("finished xen_suspend_domain\n"); cmn_err(CE_NOTE, "domain restore/migrate completed"); }