summary refs log tree commit diff
path: root/x86_64
diff options
context:
space:
mode:
authorMiriam Zimmerman <mutexlox@google.com>2019-01-29 21:21:48 -0800
committerchrome-bot <chrome-bot@chromium.org>2019-02-06 08:31:58 -0800
commit26ac928925e006b82c7b563803689529197ee824 (patch)
tree9367fa519028ba8a3d70b91e7cbe53891ae14dcf /x86_64
parent825ba5298f20fab956f555c928b6c1f3ce7c78e3 (diff)
downloadcrosvm-26ac928925e006b82c7b563803689529197ee824.tar
crosvm-26ac928925e006b82c7b563803689529197ee824.tar.gz
crosvm-26ac928925e006b82c7b563803689529197ee824.tar.bz2
crosvm-26ac928925e006b82c7b563803689529197ee824.tar.lz
crosvm-26ac928925e006b82c7b563803689529197ee824.tar.xz
crosvm-26ac928925e006b82c7b563803689529197ee824.tar.zst
crosvm-26ac928925e006b82c7b563803689529197ee824.zip
Add logic to set up PIT (guarded by flag).
BUG=chromium:908689
TEST=None

Change-Id: I625bab235f740d1d2ae256de61a25d560025b751
Reviewed-on: https://chromium-review.googlesource.com/1444501
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Miriam Zimmerman <mutexlox@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'x86_64')
-rw-r--r--x86_64/src/lib.rs48
1 files changed, 39 insertions, 9 deletions
diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs
index ed5637d..b65fe46 100644
--- a/x86_64/src/lib.rs
+++ b/x86_64/src/lib.rs
@@ -83,7 +83,7 @@ use io_jail::Minijail;
 use kvm::*;
 use resources::{AddressRanges, SystemAllocator};
 use sync::Mutex;
-use sys_util::{EventFd, GuestAddress, GuestMemory};
+use sys_util::{Clock, EventFd, GuestAddress, GuestMemory};
 
 #[derive(Debug)]
 pub enum Error {
@@ -95,6 +95,8 @@ pub enum Error {
     Cmdline(kernel_cmdline::Error),
     /// Unable to make an EventFd
     CreateEventFd(sys_util::Error),
+    /// Unable to create PIT device.
+    CreatePit(devices::PitError),
     /// Unable to create Kvm.
     CreateKvm(sys_util::Error),
     /// Unable to create a PciRoot hub.
@@ -126,6 +128,7 @@ impl error::Error for Error {
             Error::CloneEventFd(_) => "Unable to clone an EventFd",
             Error::Cmdline(_) => "the given kernel command line was invalid",
             Error::CreateEventFd(_) => "Unable to make an EventFd",
+            Error::CreatePit(_) => "Unable to make Pit device",
             Error::CreateKvm(_) => "failed to open /dev/kvm",
             Error::CreatePciRoot(_) => "failed to create a PCI root hub",
             Error::CreateSocket(_) => "failed to create socket",
@@ -286,7 +289,11 @@ fn arch_memory_regions(size: u64) -> Vec<(GuestAddress, u64)> {
 }
 
 impl arch::LinuxArch for X8664arch {
-    fn build_vm<F>(mut components: VmComponents, virtio_devs: F) -> Result<RunnableLinuxVm>
+    fn build_vm<F>(
+        mut components: VmComponents,
+        split_irqchip: bool,
+        virtio_devs: F,
+    ) -> Result<RunnableLinuxVm>
     where
         F: FnOnce(
             &GuestMemory,
@@ -297,7 +304,7 @@ impl arch::LinuxArch for X8664arch {
             Self::get_resource_allocator(components.memory_mb, components.wayland_dmabuf);
         let mem = Self::setup_memory(components.memory_mb)?;
         let kvm = Kvm::new().map_err(Error::CreateKvm)?;
-        let mut vm = Self::create_vm(&kvm, mem.clone())?;
+        let mut vm = Self::create_vm(&kvm, split_irqchip, mem.clone())?;
 
         let vcpu_count = components.vcpu_count;
         let mut vcpus = Vec::with_capacity(vcpu_count as usize);
@@ -329,6 +336,7 @@ impl arch::LinuxArch for X8664arch {
 
         let (io_bus, stdio_serial) = Self::setup_io_bus(
             &mut vm,
+            split_irqchip,
             exit_evt.try_clone().map_err(Error::CloneEventFd)?,
             Some(pci_bus.clone()),
         )?;
@@ -418,13 +426,16 @@ impl X8664arch {
     /// # Arguments
     ///
     /// * `kvm` - The opened /dev/kvm object.
+    /// * `split_irqchip` - Whether to use a split IRQ chip.
     /// * `mem` - The memory to be used by the guest.
-    fn create_vm(kvm: &Kvm, mem: GuestMemory) -> Result<Vm> {
+    fn create_vm(kvm: &Kvm, split_irqchip: bool, mem: GuestMemory) -> Result<Vm> {
         let vm = Vm::new(&kvm, mem)?;
         let tss_addr = GuestAddress(0xfffbd000);
         vm.set_tss_addr(tss_addr).expect("set tss addr failed");
-        vm.create_pit().expect("create pit failed");
-        vm.create_irq_chip()?;
+        if !split_irqchip {
+            vm.create_pit().expect("create pit failed");
+            vm.create_irq_chip()?;
+        }
         Ok(vm)
     }
 
@@ -490,9 +501,11 @@ impl X8664arch {
     /// # Arguments
     ///
     /// * - `vm` the vm object
+    /// * - `split_irqchip`: whether to use a split IRQ chip (i.e. userspace PIT/PIC/IOAPIC)
     /// * - `exit_evt` - the event fd object which should receive exit events
     fn setup_io_bus(
         vm: &mut Vm,
+        split_irqchip: bool,
         exit_evt: EventFd,
         pci: Option<Arc<Mutex<devices::PciConfigIo>>>,
     ) -> Result<(devices::Bus, Arc<Mutex<devices::Serial>>)> {
@@ -558,9 +571,26 @@ impl X8664arch {
                 false,
             )
             .unwrap();
-        io_bus
-            .insert(nul_device.clone(), 0x040, 0x8, false)
-            .unwrap(); // ignore pit
+
+        if split_irqchip {
+            let pit_evt = EventFd::new().map_err(Error::CreateEventFd)?;
+            let pit = Arc::new(Mutex::new(
+                devices::Pit::new(
+                    pit_evt.try_clone().map_err(Error::CloneEventFd)?,
+                    Arc::new(Mutex::new(Clock::new())),
+                )
+                .map_err(Error::CreatePit)?,
+            ));
+            // Reserve from 0x40 to 0x61 (the speaker).
+            io_bus.insert(pit.clone(), 0x040, 0x22, false).unwrap();
+            vm.register_irqfd(&pit_evt, 0)
+                .map_err(Error::RegisterIrqfd)?;
+        } else {
+            io_bus
+                .insert(nul_device.clone(), 0x040, 0x8, false)
+                .unwrap(); // ignore pit
+        }
+
         io_bus
             .insert(nul_device.clone(), 0x0ed, 0x1, false)
             .unwrap(); // most likely this one does nothing