mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 13:45:20 +00:00
devices: Add support for i8042 reset device
Introduce emulation of i8042 device to allow the guest to stop the VM by issuing a reset event. The device has been copied over from the Crosvm code base, relying on the commit 0268e26e1ac9e09aa51d733482c5df139cd8d588. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
29b90a8aee
commit
342bdc3619
42
devices/src/legacy/i8042.rs
Normal file
42
devices/src/legacy/i8042.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
use vmm_sys_util::EventFd;
|
||||||
|
|
||||||
|
use BusDevice;
|
||||||
|
|
||||||
|
/// A i8042 PS/2 controller that emulates just enough to shutdown the machine.
|
||||||
|
pub struct I8042Device {
|
||||||
|
reset_evt: EventFd,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl I8042Device {
|
||||||
|
/// Constructs a i8042 device that will signal the given event when the guest requests it.
|
||||||
|
pub fn new(reset_evt: EventFd) -> I8042Device {
|
||||||
|
I8042Device { reset_evt }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// i8042 device is located at I/O port 0x61. We partially implement two 8-bit
|
||||||
|
// registers: port 0x61 (I8042_PORT_B_REG, offset 0 from base of 0x61), and
|
||||||
|
// port 0x64 (I8042_COMMAND_REG, offset 3 from base of 0x61).
|
||||||
|
impl BusDevice for I8042Device {
|
||||||
|
fn read(&mut self, offset: u64, data: &mut [u8]) {
|
||||||
|
if data.len() == 1 && offset == 3 {
|
||||||
|
data[0] = 0x0;
|
||||||
|
} else if data.len() == 1 && offset == 0 {
|
||||||
|
// Like kvmtool, we return bit 5 set in I8042_PORT_B_REG to
|
||||||
|
// avoid hang in pit_calibrate_tsc() in Linux kernel.
|
||||||
|
data[0] = 0x20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, offset: u64, data: &[u8]) {
|
||||||
|
if data.len() == 1 && data[0] == 0xfe && offset == 3 {
|
||||||
|
if let Err(e) = self.reset_evt.write(1) {
|
||||||
|
println!("Error triggering i8042 reset event: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,5 +6,7 @@
|
|||||||
// found in the THIRD-PARTY file.
|
// found in the THIRD-PARTY file.
|
||||||
|
|
||||||
mod serial;
|
mod serial;
|
||||||
|
mod i8042;
|
||||||
|
|
||||||
pub use self::serial::Serial;
|
pub use self::serial::Serial;
|
||||||
|
pub use self::i8042::I8042Device;
|
||||||
|
@ -213,6 +213,9 @@ struct DeviceManager {
|
|||||||
// Serial port on 0x3f8
|
// Serial port on 0x3f8
|
||||||
serial: Arc<Mutex<devices::legacy::Serial>>,
|
serial: Arc<Mutex<devices::legacy::Serial>>,
|
||||||
serial_evt: EventFd,
|
serial_evt: EventFd,
|
||||||
|
|
||||||
|
// i8042 device for exit
|
||||||
|
i8042: Arc<Mutex<devices::legacy::I8042Device>>,
|
||||||
exit_evt: EventFd,
|
exit_evt: EventFd,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,20 +229,31 @@ impl DeviceManager {
|
|||||||
)));
|
)));
|
||||||
|
|
||||||
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFd)?;
|
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFd)?;
|
||||||
|
let i8042 = Arc::new(Mutex::new(devices::legacy::I8042Device::new(
|
||||||
|
exit_evt.try_clone().map_err(Error::EventFd)?,
|
||||||
|
)));
|
||||||
|
|
||||||
Ok(DeviceManager {
|
Ok(DeviceManager {
|
||||||
io_bus,
|
io_bus,
|
||||||
serial,
|
serial,
|
||||||
serial_evt,
|
serial_evt,
|
||||||
|
i8042,
|
||||||
exit_evt,
|
exit_evt,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register legacy devices.
|
/// Register legacy devices.
|
||||||
pub fn register_devices(&mut self) -> Result<()> {
|
pub fn register_devices(&mut self) -> Result<()> {
|
||||||
|
// Insert serial device
|
||||||
self.io_bus
|
self.io_bus
|
||||||
.insert(self.serial.clone(), 0x3f8, 0x8)
|
.insert(self.serial.clone(), 0x3f8, 0x8)
|
||||||
.map_err(Error::BusError)?;
|
.map_err(Error::BusError)?;
|
||||||
|
|
||||||
|
// Insert i8042 device
|
||||||
|
self.io_bus
|
||||||
|
.insert(self.i8042.clone(), 0x61, 0x4)
|
||||||
|
.map_err(Error::BusError)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user