static void ps_md_data_handler(ds_cb_arg_t arg, void *buf, size_t buflen) { extern int mach_descrip_update(void); extern void mdeg_notify_clients(void); extern void recalc_xc_timeouts(void); ds_svc_hdl_t ds_handle = ds_md_handle; platsvc_md_update_req_t *msg = buf; platsvc_md_update_resp_t resp_msg; uint_t rv; if (arg == NULL) return; if (ds_handle == DS_INVALID_HDL) { DBG("ps_md_data_handler: DS handle no longer valid\n"); return; } if (msg == NULL || buflen != sizeof (platsvc_md_update_req_t)) { resp_msg.req_num = 0; resp_msg.result = MD_UPDATE_INVALID_MSG; if ((rv = ds_cap_send(ds_handle, &resp_msg, sizeof (resp_msg))) != 0) { cmn_err(CE_NOTE, "md ds_cap_send failed (%d)", rv); } return; } DBG("MD Reload...\n"); if (mach_descrip_update()) { cmn_err(CE_WARN, "MD reload failed\n"); return; } recalc_xc_timeouts(); /* * notify registered clients that MD has * been updated */ mdeg_notify_clients(); resp_msg.req_num = msg->req_num; resp_msg.result = MD_UPDATE_SUCCESS; if ((rv = ds_cap_send(ds_handle, &resp_msg, sizeof (resp_msg))) != 0) { cmn_err(CE_NOTE, "md ds_cap_send resp failed (%d)", rv); } }
/* * Initialize the kernel's Machine Description(MD) framework * after the the VM system has been initialized. * * Also get the most recent version of the MD. * Assumes that the machine description frame work is in a clean * state and the machine description intialized during startup * has been cleaned up and resources deallocated. */ void mach_descrip_init(void) { ASSERT((curr_mach_descrip == NULL && curr_mach_descrip_memops == NULL)); curr_mach_descrip_memops = &mach_descrip_memops; curr_mach_descrip = new_mach_descrip(); if (curr_mach_descrip == NULL) panic("Allocation for machine description failed\n"); if (mach_descrip_update()) panic("Machine description intialization failed\n"); /* read in global params */ init_md_params(); }
/* * Initialize the kernel's Machine Description(MD) framework * early on in startup during mlsetup() so consumers * can get to the MD before the VM system has been initialized. * * Also get the most recent version of the MD. */ void mach_descrip_startup_init(void) { mutex_init(&curr_mach_descrip_lock, NULL, MUTEX_DRIVER, NULL); mutex_init(&obs_list_lock, NULL, MUTEX_DRIVER, NULL); obs_machine_descrip_list = NULL; curr_mach_descrip_memops = &startup_memops; curr_mach_descrip = new_mach_descrip(); if (curr_mach_descrip == NULL) panic("Allocation for machine description failed\n"); if (mach_descrip_update()) panic("Machine description initialization failed\n"); }
/*ARGSUSED*/ int suspend_start(char *error_reason, size_t max_reason_len) { uint64_t source_tick; uint64_t source_stick; uint64_t rv; timestruc_t source_tod; int spl; ASSERT(suspend_supported()); DBG("suspend: %s", __func__); sfmmu_ctxdoms_lock(); mutex_enter(&cpu_lock); /* Suspend the watchdog */ watchdog_suspend(); /* Record the TOD */ mutex_enter(&tod_lock); source_tod = tod_get(); mutex_exit(&tod_lock); /* Pause all other CPUs */ pause_cpus(NULL); DBG_PROM("suspend: CPUs paused\n"); /* Suspend cyclics */ cyclic_suspend(); DBG_PROM("suspend: cyclics suspended\n"); /* Disable interrupts */ spl = spl8(); DBG_PROM("suspend: spl8()\n"); source_tick = gettick_counter(); source_stick = gettick(); DBG_PROM("suspend: source_tick: 0x%lx\n", source_tick); DBG_PROM("suspend: source_stick: 0x%lx\n", source_stick); /* * Call into the HV to initiate the suspend. hv_guest_suspend() * returns after the guest has been resumed or if the suspend * operation failed or was cancelled. After a successful suspend, * the %tick and %stick registers may have changed by an amount * that is not proportional to the amount of time that has passed. * They may have jumped forwards or backwards. Some variation is * allowed and accounted for using suspend_tick_stick_max_delta, * but otherwise this jump must be uniform across all CPUs and we * operate under the assumption that it is (maintaining two global * offset variables--one for %tick and one for %stick.) */ DBG_PROM("suspend: suspending... \n"); rv = hv_guest_suspend(); if (rv != 0) { splx(spl); cyclic_resume(); start_cpus(); watchdog_resume(); mutex_exit(&cpu_lock); sfmmu_ctxdoms_unlock(); DBG("suspend: failed, rv: %ld\n", rv); return (rv); } suspend_count++; /* Update the global tick and stick offsets and the preserved TOD */ set_tick_offsets(source_tick, source_stick, &source_tod); /* Ensure new offsets are globally visible before resuming CPUs */ membar_sync(); /* Enable interrupts */ splx(spl); /* Set the {%tick,%stick}.NPT bits on all CPUs */ if (enable_user_tick_stick_emulation) { xc_all((xcfunc_t *)enable_tick_stick_npt, NULL, NULL); xt_sync(cpu_ready_set); ASSERT(gettick_npt() != 0); ASSERT(getstick_npt() != 0); } /* If emulation is enabled, but not currently active, enable it */ if (enable_user_tick_stick_emulation && !tick_stick_emulation_active) { tick_stick_emulation_active = B_TRUE; } sfmmu_ctxdoms_remove(); /* Resume cyclics, unpause CPUs */ cyclic_resume(); start_cpus(); /* Set the TOD */ mutex_enter(&tod_lock); tod_set(source_tod); mutex_exit(&tod_lock); /* Re-enable the watchdog */ watchdog_resume(); mutex_exit(&cpu_lock); /* Download the latest MD */ if ((rv = mach_descrip_update()) != 0) cmn_err(CE_PANIC, "suspend: mach_descrip_update failed: %ld", rv); sfmmu_ctxdoms_update(); sfmmu_ctxdoms_unlock(); /* Get new MD, update CPU mappings/relationships */ if (suspend_update_cpu_mappings) update_cpu_mappings(); DBG("suspend: target tick: 0x%lx", gettick_counter()); DBG("suspend: target stick: 0x%llx", gettick()); DBG("suspend: user %%tick/%%stick emulation is %d", tick_stick_emulation_active); DBG("suspend: finished"); return (0); }