crosvm: flag to disable legacy x86 IO devices.

BUG=b:179648314
TEST=Keyboard pass-through enabled.

Change-Id: Ie2e5fdc85367ddb9d5f216291773cf8065d8c956
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2885078
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Tomasz Jeznach <tjeznach@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
diff --git a/arch/src/lib.rs b/arch/src/lib.rs
index 91b4b67..31a94c4 100644
--- a/arch/src/lib.rs
+++ b/arch/src/lib.rs
@@ -92,6 +92,7 @@
     #[cfg(all(target_arch = "x86_64", feature = "gdb"))]
     pub gdb: Option<(u32, Tube)>, // port and control tube.
     pub dmi_path: Option<PathBuf>,
+    pub no_legacy: bool,
 }
 
 /// Holds the elements needed to run a Linux VM. Created by `build_vm`.
diff --git a/src/crosvm.rs b/src/crosvm.rs
index 7a4318a..e40c54f 100644
--- a/src/crosvm.rs
+++ b/src/crosvm.rs
@@ -264,6 +264,7 @@
     #[cfg(feature = "direct")]
     pub direct_edge_irq: Vec<u32>,
     pub dmi_path: Option<PathBuf>,
+    pub no_legacy: bool,
 }
 
 impl Default for Config {
@@ -340,6 +341,7 @@
             #[cfg(feature = "direct")]
             direct_edge_irq: Vec::new(),
             dmi_path: None,
+            no_legacy: false,
         }
     }
 }
diff --git a/src/linux.rs b/src/linux.rs
index 9632dbd..d0f8f07 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -2325,6 +2325,7 @@
         #[cfg(all(target_arch = "x86_64", feature = "gdb"))]
         gdb: None,
         dmi_path: cfg.dmi_path.clone(),
+        no_legacy: cfg.no_legacy,
     })
 }
 
diff --git a/src/main.rs b/src/main.rs
index e86845a..2d951a0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1751,6 +1751,9 @@
             }
             cfg.dmi_path = Some(dmi_path);
         }
+        "no-legacy" => {
+            cfg.no_legacy = true;
+        }
         "help" => return Err(argument::Error::PrintHelp),
         _ => unreachable!(),
     }
@@ -1972,6 +1975,7 @@
           #[cfg(feature = "direct")]
           Argument::value("direct-edge-irq", "irq", "Enable interrupt passthrough"),
           Argument::value("dmi", "DIR", "Directory with smbios_entry_point/DMI files"),
+          Argument::flag("no-legacy", "Don't use legacy KBD/RTC devices emulation"),
           Argument::short_flag('h', "help", "Print help message.")];
 
     let mut cfg = Config::default();
diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs
index 91dde5d..b8444db 100644
--- a/x86_64/src/lib.rs
+++ b/x86_64/src/lib.rs
@@ -409,18 +409,19 @@
         )
         .map_err(Error::CreatePciRoot)?;
         let pci_bus = Arc::new(Mutex::new(PciConfigIo::new(pci)));
+        io_bus.insert(pci_bus, 0xcf8, 0x8).unwrap();
 
         // Event used to notify crosvm that guest OS is trying to suspend.
         let suspend_evt = Event::new().map_err(Error::CreateEvent)?;
 
-        Self::setup_io_bus(
-            &mut io_bus,
-            irq_chip.pit_uses_speaker_port(),
-            exit_evt.try_clone().map_err(Error::CloneEvent)?,
-            Some(pci_bus),
-            components.memory_size,
-        )?;
-
+        if !components.no_legacy {
+            Self::setup_legacy_devices(
+                &mut io_bus,
+                irq_chip.pit_uses_speaker_port(),
+                exit_evt.try_clone().map_err(Error::CloneEvent)?,
+                components.memory_size,
+            )?;
+        }
         Self::setup_serial_devices(
             components.protected_vm,
             irq_chip.as_irq_chip_mut(),
@@ -947,7 +948,7 @@
         cmdline
     }
 
-    /// Sets up the IO bus for this platform
+    /// Sets up the legacy x86 IO platform devices
     ///
     /// # Arguments
     ///
@@ -955,11 +956,10 @@
     /// * - `pit_uses_speaker_port` - does the PIT use port 0x61 for the PC speaker
     /// * - `exit_evt` - the event object which should receive exit events
     /// * - `mem_size` - the size in bytes of physical ram for the guest
-    fn setup_io_bus(
+    fn setup_legacy_devices(
         io_bus: &mut devices::Bus,
         pit_uses_speaker_port: bool,
         exit_evt: Event,
-        pci: Option<Arc<Mutex<devices::PciConfigIo>>>,
         mem_size: u64,
     ) -> Result<()> {
         struct NoDevice;
@@ -1005,13 +1005,6 @@
         io_bus.insert(nul_device.clone(), 0x0ed, 0x1).unwrap(); // most likely this one does nothing
         io_bus.insert(nul_device.clone(), 0x0f0, 0x2).unwrap(); // ignore fpu
 
-        if let Some(pci_root) = pci {
-            io_bus.insert(pci_root, 0xcf8, 0x8).unwrap();
-        } else {
-            // ignore pci.
-            io_bus.insert(nul_device, 0xcf8, 0x8).unwrap();
-        }
-
         Ok(())
     }
 
diff --git a/x86_64/src/test_integration.rs b/x86_64/src/test_integration.rs
index 051a401..551a259 100644
--- a/x86_64/src/test_integration.rs
+++ b/x86_64/src/test_integration.rs
@@ -137,12 +137,12 @@
     )
     .unwrap();
     let pci_bus = Arc::new(Mutex::new(PciConfigIo::new(pci)));
+    io_bus.insert(pci_bus, 0xcf8, 0x8).unwrap();
 
-    X8664arch::setup_io_bus(
+    X8664arch::setup_legacy_devices(
         &mut io_bus,
         irq_chip.pit_uses_speaker_port(),
         exit_evt.try_clone().unwrap(),
-        Some(pci_bus),
         memory_size,
     )
     .unwrap();