vm: Make triple-fault and i8042 reset reboot the VM

Now we have ACPI shutdown we should reboot on these reset triggers.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2019-08-29 16:39:00 +01:00 committed by Samuel Ortiz
parent 5a187ee2c2
commit 614eb68f16

View File

@ -464,33 +464,37 @@ impl Vcpu {
/// ///
/// Note that the state of the VCPU and associated VM must be setup first for this to do /// Note that the state of the VCPU and associated VM must be setup first for this to do
/// anything useful. /// anything useful.
pub fn run(&self) -> Result<()> { pub fn run(&self) -> Result<bool> {
match self.fd.run() { match self.fd.run() {
Ok(run) => match run { Ok(run) => match run {
VcpuExit::IoIn(addr, data) => { VcpuExit::IoIn(addr, data) => {
self.io_bus.read(u64::from(addr), data); self.io_bus.read(u64::from(addr), data);
Ok(()) Ok(true)
} }
VcpuExit::IoOut(addr, data) => { VcpuExit::IoOut(addr, data) => {
if addr == DEBUG_IOPORT && data.len() == 1 { if addr == DEBUG_IOPORT && data.len() == 1 {
self.log_debug_ioport(data[0]); self.log_debug_ioport(data[0]);
} }
self.io_bus.write(u64::from(addr), data); self.io_bus.write(u64::from(addr), data);
Ok(()) Ok(true)
} }
VcpuExit::MmioRead(addr, data) => { VcpuExit::MmioRead(addr, data) => {
self.mmio_bus.read(addr as u64, data); self.mmio_bus.read(addr as u64, data);
Ok(()) Ok(true)
} }
VcpuExit::MmioWrite(addr, data) => { VcpuExit::MmioWrite(addr, data) => {
self.mmio_bus.write(addr as u64, data); self.mmio_bus.write(addr as u64, data);
Ok(()) Ok(true)
} }
VcpuExit::IoapicEoi(vector) => { VcpuExit::IoapicEoi(vector) => {
if let Some(ioapic) = &self.ioapic { if let Some(ioapic) = &self.ioapic {
ioapic.lock().unwrap().end_of_interrupt(vector); ioapic.lock().unwrap().end_of_interrupt(vector);
} }
Ok(()) Ok(true)
}
VcpuExit::Shutdown => {
// Triple fault to trigger a reboot
Ok(false)
} }
r => { r => {
error!("Unexpected exit reason on vcpu run: {:?}", r); error!("Unexpected exit reason on vcpu run: {:?}", r);
@ -499,7 +503,7 @@ impl Vcpu {
}, },
Err(ref e) => match e.raw_os_error().unwrap() { Err(ref e) => match e.raw_os_error().unwrap() {
libc::EAGAIN | libc::EINTR => Ok(()), libc::EAGAIN | libc::EINTR => Ok(true),
_ => { _ => {
error!("VCPU {:?} error {:?}", self.id, e); error!("VCPU {:?} error {:?}", self.id, e);
Err(Error::VcpuUnhandledKvmExit) Err(Error::VcpuUnhandledKvmExit)
@ -687,7 +691,7 @@ impl DeviceManager {
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(DeviceManagerError::EventFd)?; let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(DeviceManagerError::EventFd)?;
let reset_evt = EventFd::new(EFD_NONBLOCK).map_err(DeviceManagerError::EventFd)?; let reset_evt = EventFd::new(EFD_NONBLOCK).map_err(DeviceManagerError::EventFd)?;
let i8042 = Arc::new(Mutex::new(devices::legacy::I8042Device::new( let i8042 = Arc::new(Mutex::new(devices::legacy::I8042Device::new(
exit_evt.try_clone().map_err(DeviceManagerError::EventFd)?, reset_evt.try_clone().map_err(DeviceManagerError::EventFd)?,
))); )));
let acpi_device = Arc::new(Mutex::new(devices::AcpiShutdownDevice::new( let acpi_device = Arc::new(Mutex::new(devices::AcpiShutdownDevice::new(
exit_evt.try_clone().map_err(DeviceManagerError::EventFd)?, exit_evt.try_clone().map_err(DeviceManagerError::EventFd)?,
@ -1820,7 +1824,7 @@ impl<'a> Vm<'a> {
let vcpu_thread_barrier = vcpu_thread_barrier.clone(); let vcpu_thread_barrier = vcpu_thread_barrier.clone();
let exit_evt = self.devices.exit_evt.try_clone().unwrap(); let reset_evt = self.devices.reset_evt.try_clone().unwrap();
self.vcpus.push( self.vcpus.push(
thread::Builder::new() thread::Builder::new()
.name(format!("cloud-hypervisor_vcpu{}", vcpu.id)) .name(format!("cloud-hypervisor_vcpu{}", vcpu.id))
@ -1841,8 +1845,19 @@ impl<'a> Vm<'a> {
// Block until all CPUs are ready. // Block until all CPUs are ready.
vcpu_thread_barrier.wait(); vcpu_thread_barrier.wait();
while vcpu.run().is_ok() {} loop {
exit_evt.write(1).unwrap(); // vcpu.run() returns false on a KVM_EXIT_SHUTDOWN (triple-fault) so trigger a reset
match vcpu.run() {
Err(e) => {
error!("VCPU generated error: {:?}", e);
}
Ok(true) => {}
Ok(false) => {
reset_evt.write(1).unwrap();
break;
}
}
}
}) })
.map_err(Error::VcpuSpawn)?, .map_err(Error::VcpuSpawn)?,
); );