mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-09-28 17:45:44 +00:00
vmm: Make gdb break/resuming more resilient
When starting the VM such that it is already on a breakpoint (via stop_on_boot) when attached to gdb then start the vCPUs in a paused state rather than starting the vCPUs later (upon resume). Further, make the resumption/break of the VM more resilient by only attempting to resume the vCPUs if were are already in a break point and only attempting to pause/break if we were already running. Fixes: #4354 Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
23352c4945
commit
0e29379bcf
@ -1048,7 +1048,12 @@ impl CpuManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Start up as many vCPUs threads as needed to reach `desired_vcpus`
|
/// Start up as many vCPUs threads as needed to reach `desired_vcpus`
|
||||||
fn activate_vcpus(&mut self, desired_vcpus: u8, inserting: bool) -> Result<()> {
|
fn activate_vcpus(
|
||||||
|
&mut self,
|
||||||
|
desired_vcpus: u8,
|
||||||
|
inserting: bool,
|
||||||
|
paused: Option<bool>,
|
||||||
|
) -> Result<()> {
|
||||||
if desired_vcpus > self.config.max_vcpus {
|
if desired_vcpus > self.config.max_vcpus {
|
||||||
return Err(Error::DesiredVCpuCountExceedsMax);
|
return Err(Error::DesiredVCpuCountExceedsMax);
|
||||||
}
|
}
|
||||||
@ -1057,11 +1062,16 @@ impl CpuManager {
|
|||||||
(desired_vcpus - self.present_vcpus() + 1) as usize,
|
(desired_vcpus - self.present_vcpus() + 1) as usize,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if let Some(paused) = paused {
|
||||||
|
self.vcpus_pause_signalled.store(paused, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Starting vCPUs: desired = {}, allocated = {}, present = {}",
|
"Starting vCPUs: desired = {}, allocated = {}, present = {}, paused = {}",
|
||||||
desired_vcpus,
|
desired_vcpus,
|
||||||
self.vcpus.len(),
|
self.vcpus.len(),
|
||||||
self.present_vcpus()
|
self.present_vcpus(),
|
||||||
|
self.vcpus_pause_signalled.load(Ordering::SeqCst)
|
||||||
);
|
);
|
||||||
|
|
||||||
// This reuses any inactive vCPUs as well as any that were newly created
|
// This reuses any inactive vCPUs as well as any that were newly created
|
||||||
@ -1101,26 +1111,16 @@ impl CpuManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Starts all the vCPUs that the VM is booting with. Blocks until all vCPUs are running.
|
// Starts all the vCPUs that the VM is booting with. Blocks until all vCPUs are running.
|
||||||
pub fn start_boot_vcpus(&mut self) -> Result<()> {
|
pub fn start_boot_vcpus(&mut self, paused: bool) -> Result<()> {
|
||||||
self.activate_vcpus(self.boot_vcpus(), false)
|
self.activate_vcpus(self.boot_vcpus(), false, Some(paused))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_restored_vcpus(&mut self) -> Result<()> {
|
pub fn start_restored_vcpus(&mut self) -> Result<()> {
|
||||||
let vcpu_numbers = self.vcpus.len() as u8;
|
self.activate_vcpus(self.vcpus.len() as u8, false, Some(true))
|
||||||
let vcpu_thread_barrier = Arc::new(Barrier::new((vcpu_numbers + 1) as usize));
|
|
||||||
// Restore the vCPUs in "paused" state.
|
|
||||||
self.vcpus_pause_signalled.store(true, Ordering::SeqCst);
|
|
||||||
|
|
||||||
for vcpu_id in 0..vcpu_numbers {
|
|
||||||
let vcpu = Arc::clone(&self.vcpus[vcpu_id as usize]);
|
|
||||||
|
|
||||||
self.start_vcpu(vcpu, vcpu_id, vcpu_thread_barrier.clone(), false)
|
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
Error::StartRestoreVcpu(anyhow!("Failed to start restored vCPUs: {:#?}", e))
|
Error::StartRestoreVcpu(anyhow!("Failed to start restored vCPUs: {:#?}", e))
|
||||||
})?;
|
})?;
|
||||||
}
|
|
||||||
// Unblock all restored CPU threads.
|
|
||||||
vcpu_thread_barrier.wait();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1136,7 +1136,7 @@ impl CpuManager {
|
|||||||
match desired_vcpus.cmp(&self.present_vcpus()) {
|
match desired_vcpus.cmp(&self.present_vcpus()) {
|
||||||
cmp::Ordering::Greater => {
|
cmp::Ordering::Greater => {
|
||||||
self.create_vcpus(desired_vcpus, None)?;
|
self.create_vcpus(desired_vcpus, None)?;
|
||||||
self.activate_vcpus(desired_vcpus, true)?;
|
self.activate_vcpus(desired_vcpus, true, None)?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
cmp::Ordering::Less => {
|
cmp::Ordering::Less => {
|
||||||
|
@ -2143,13 +2143,11 @@ impl Vm {
|
|||||||
self.vm.tdx_finalize().map_err(Error::FinalizeTdx)?;
|
self.vm.tdx_finalize().map_err(Error::FinalizeTdx)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if new_state == VmState::Running {
|
|
||||||
self.cpu_manager
|
self.cpu_manager
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.start_boot_vcpus()
|
.start_boot_vcpus(new_state == VmState::BreakPoint)
|
||||||
.map_err(Error::CpuManager)?;
|
.map_err(Error::CpuManager)?;
|
||||||
}
|
|
||||||
|
|
||||||
let mut state = self.state.try_write().map_err(|_| Error::PoisonedState)?;
|
let mut state = self.state.try_write().map_err(|_| Error::PoisonedState)?;
|
||||||
*state = new_state;
|
*state = new_state;
|
||||||
@ -2885,9 +2883,10 @@ impl Debuggable for Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn debug_pause(&mut self) -> std::result::Result<(), DebuggableError> {
|
fn debug_pause(&mut self) -> std::result::Result<(), DebuggableError> {
|
||||||
if !self.cpu_manager.lock().unwrap().vcpus_paused() {
|
if *self.state.read().unwrap() == VmState::Running {
|
||||||
self.pause().map_err(DebuggableError::Pause)?;
|
self.pause().map_err(DebuggableError::Pause)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut state = self
|
let mut state = self
|
||||||
.state
|
.state
|
||||||
.try_write()
|
.try_write()
|
||||||
@ -2897,25 +2896,10 @@ impl Debuggable for Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn debug_resume(&mut self) -> std::result::Result<(), DebuggableError> {
|
fn debug_resume(&mut self) -> std::result::Result<(), DebuggableError> {
|
||||||
if !self.cpu_manager.lock().unwrap().vcpus_paused() {
|
if *self.state.read().unwrap() == VmState::BreakPoint {
|
||||||
self.cpu_manager
|
self.resume().map_err(DebuggableError::Pause)?;
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.start_boot_vcpus()
|
|
||||||
.map_err(|e| {
|
|
||||||
DebuggableError::Resume(MigratableError::Resume(anyhow!(
|
|
||||||
"Could not start boot vCPUs: {:?}",
|
|
||||||
e
|
|
||||||
)))
|
|
||||||
})?;
|
|
||||||
} else {
|
|
||||||
self.resume().map_err(DebuggableError::Resume)?;
|
|
||||||
}
|
}
|
||||||
let mut state = self
|
|
||||||
.state
|
|
||||||
.try_write()
|
|
||||||
.map_err(|_| DebuggableError::PoisonedState)?;
|
|
||||||
*state = VmState::Running;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user