summary refs log tree commit diff
path: root/x86_64
diff options
context:
space:
mode:
authorZhuocheng Ding <zhuocheng.ding@intel.corp-partner.google.com>2019-12-02 15:50:20 +0800
committerCommit Bot <commit-bot@chromium.org>2020-03-05 01:02:48 +0000
commitf2e90bf0b0ca101d2925e91ca50d3e9e5ea2fdb7 (patch)
tree20a8210f21c3e530c80e45146fbb91f284064507 /x86_64
parent50740cece43671cc42035f92cde460aad3d29494 (diff)
downloadcrosvm-f2e90bf0b0ca101d2925e91ca50d3e9e5ea2fdb7.tar
crosvm-f2e90bf0b0ca101d2925e91ca50d3e9e5ea2fdb7.tar.gz
crosvm-f2e90bf0b0ca101d2925e91ca50d3e9e5ea2fdb7.tar.bz2
crosvm-f2e90bf0b0ca101d2925e91ca50d3e9e5ea2fdb7.tar.lz
crosvm-f2e90bf0b0ca101d2925e91ca50d3e9e5ea2fdb7.tar.xz
crosvm-f2e90bf0b0ca101d2925e91ca50d3e9e5ea2fdb7.tar.zst
crosvm-f2e90bf0b0ca101d2925e91ca50d3e9e5ea2fdb7.zip
Add logic to setup PIC/IOAPIC.
TODO: Route irqfd to PIC/IOAPIC to make them fully work.

BUG=chromium:908689
TEST=None

Change-Id: I301287b1cf32cfccffce6c52ebbb5e123931178e
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1945796
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Zhuocheng Ding <zhuocheng.ding@intel.corp-partner.google.com>
Diffstat (limited to 'x86_64')
-rw-r--r--x86_64/Cargo.toml1
-rw-r--r--x86_64/src/lib.rs40
2 files changed, 39 insertions, 2 deletions
diff --git a/x86_64/Cargo.toml b/x86_64/Cargo.toml
index bb1c445..49ef53f 100644
--- a/x86_64/Cargo.toml
+++ b/x86_64/Cargo.toml
@@ -20,3 +20,4 @@ resources = { path = "../resources" }
 sync = { path = "../sync" }
 sys_util = { path = "../sys_util" }
 acpi_tables = {path = "../acpi_tables" }
+vm_control = { path = "../vm_control" }
diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs
index b6f18e3..d9fe8a9 100644
--- a/x86_64/src/lib.rs
+++ b/x86_64/src/lib.rs
@@ -55,13 +55,17 @@ use std::sync::Arc;
 
 use crate::bootparam::boot_params;
 use arch::{RunnableLinuxVm, VmComponents, VmImage};
-use devices::{get_serial_tty_string, PciConfigIo, PciDevice, PciInterruptPin, SerialParameters};
+use devices::{
+    get_serial_tty_string, Ioapic, PciConfigIo, PciDevice, PciInterruptPin, Pic, SerialParameters,
+    IOAPIC_BASE_ADDRESS, IOAPIC_MEM_LENGTH_BYTES,
+};
 use io_jail::Minijail;
 use kvm::*;
 use remain::sorted;
 use resources::SystemAllocator;
 use sync::Mutex;
 use sys_util::{Clock, EventFd, GuestAddress, GuestMemory, GuestMemoryError};
+use vm_control::VmIrqRequestSocket;
 
 #[sorted]
 #[derive(Debug)]
@@ -73,6 +77,7 @@ pub enum Error {
     CreateDevices(Box<dyn StdError>),
     CreateEventFd(sys_util::Error),
     CreateFdt(arch::fdt::Error),
+    CreateIoapicDevice(sys_util::Error),
     CreateIrqChip(sys_util::Error),
     CreateKvm(sys_util::Error),
     CreatePciRoot(arch::DeviceRegistrationError),
@@ -120,6 +125,7 @@ impl Display for Error {
             CreateDevices(e) => write!(f, "error creating devices: {}", e),
             CreateEventFd(e) => write!(f, "unable to make an EventFd: {}", e),
             CreateFdt(e) => write!(f, "failed to create fdt: {}", e),
+            CreateIoapicDevice(e) => write!(f, "failed to create IOAPIC device: {}", e),
             CreateIrqChip(e) => write!(f, "failed to create irq chip: {}", e),
             CreateKvm(e) => write!(f, "failed to open /dev/kvm: {}", e),
             CreatePciRoot(e) => write!(f, "failed to create a PCI root hub: {}", e),
@@ -314,6 +320,7 @@ impl arch::LinuxArch for X8664arch {
     fn build_vm<F, E>(
         mut components: VmComponents,
         split_irqchip: bool,
+        ioapic_device_socket: VmIrqRequestSocket,
         serial_parameters: &BTreeMap<u8, SerialParameters>,
         serial_jail: Option<Minijail>,
         create_devices: F,
@@ -362,6 +369,23 @@ impl arch::LinuxArch for X8664arch {
 
         let exit_evt = EventFd::new().map_err(Error::CreateEventFd)?;
 
+        let split_irqchip = if split_irqchip {
+            let pic = Arc::new(Mutex::new(Pic::new()));
+            let ioapic = Arc::new(Mutex::new(
+                Ioapic::new(&mut vm, ioapic_device_socket).map_err(Error::CreateIoapicDevice)?,
+            ));
+            mmio_bus
+                .insert(
+                    ioapic.clone(),
+                    IOAPIC_BASE_ADDRESS,
+                    IOAPIC_MEM_LENGTH_BYTES,
+                    false,
+                )
+                .unwrap();
+            Some((pic, ioapic))
+        } else {
+            None
+        };
         let pci_devices = create_devices(&mem, &mut vm, &mut resources, &exit_evt)
             .map_err(|e| Error::CreateDevices(Box::new(e)))?;
         let (pci, pci_irqs, pid_debug_label_map) =
@@ -376,7 +400,7 @@ impl arch::LinuxArch for X8664arch {
 
         let mut io_bus = Self::setup_io_bus(
             &mut vm,
-            split_irqchip,
+            split_irqchip.is_some(),
             exit_evt.try_clone().map_err(Error::CloneEventFd)?,
             Some(pci_bus.clone()),
             components.memory_size,
@@ -394,6 +418,17 @@ impl arch::LinuxArch for X8664arch {
             None => None,
         };
 
+        if let Some((pic, _)) = &split_irqchip {
+            io_bus.insert(pic.clone(), 0x20, 0x2, true).unwrap();
+            io_bus.insert(pic.clone(), 0xa0, 0x2, true).unwrap();
+            io_bus.insert(pic.clone(), 0x4d0, 0x2, true).unwrap();
+
+            let mut irq_num = resources.allocate_irq().unwrap();
+            while irq_num < kvm::NUM_IOAPIC_PINS as u32 {
+                irq_num = resources.allocate_irq().unwrap();
+            }
+        }
+
         match components.vm_image {
             VmImage::Bios(ref mut bios) => Self::load_bios(&mem, bios)?,
             VmImage::Kernel(ref mut kernel_image) => {
@@ -447,6 +482,7 @@ impl arch::LinuxArch for X8664arch {
             vcpus,
             vcpu_affinity,
             irq_chip,
+            split_irqchip,
             io_bus,
             mmio_bus,
             pid_debug_label_map,