(&mut self)
| 3273 | } |
| 3274 | |
| 3275 | fn resume(&mut self) -> std::result::Result<(), MigratableError> { |
| 3276 | event!("vm", "resuming"); |
| 3277 | let current_state = self.get_state(); |
| 3278 | let new_state = VmState::Running; |
| 3279 | |
| 3280 | self.state |
| 3281 | .valid_transition(new_state) |
| 3282 | .map_err(|e| MigratableError::Resume(anyhow!("Invalid transition: {e:?}")))?; |
| 3283 | |
| 3284 | // Restore KVM clock BEFORE vCPUs start running, so they see correct |
| 3285 | // TSC/kvmclock from the first instruction after resume. |
| 3286 | #[cfg(target_arch = "x86_64")] |
| 3287 | { |
| 3288 | if let Some(clock) = &self.saved_clock { |
| 3289 | self.vm |
| 3290 | .set_clock(clock) |
| 3291 | .map_err(|e| MigratableError::Resume(anyhow!("Could not set VM clock: {e}")))?; |
| 3292 | } |
| 3293 | } |
| 3294 | |
| 3295 | if current_state == VmState::Paused { |
| 3296 | self.vm |
| 3297 | .resume() |
| 3298 | .map_err(|e| MigratableError::Resume(anyhow!("Could not resume the VM: {e}")))?; |
| 3299 | } |
| 3300 | |
| 3301 | self.device_manager.lock().unwrap().resume()?; |
| 3302 | self.cpu_manager.lock().unwrap().resume()?; |
| 3303 | |
| 3304 | // And we're back to the Running state. |
| 3305 | self.state = new_state; |
| 3306 | event!("vm", "resumed"); |
| 3307 | Ok(()) |
| 3308 | } |
| 3309 | } |
| 3310 | |
| 3311 | #[derive(Serialize, Deserialize)] |
no test coverage detected