summary refs log tree commit diff
path: root/x86_64
diff options
context:
space:
mode:
authorTomasz Jeznach <tjeznach@chromium.org>2020-05-01 09:54:59 -0700
committerCommit Bot <commit-bot@chromium.org>2020-05-05 00:03:46 +0000
commite94b5f84da58d7f74a2c093143b665699c1bebca (patch)
treeded356f3de7bd0b56fe6394b342f3460aa69e121 /x86_64
parent6fe08fa36338ee6339dd4748173865763bfc7b31 (diff)
downloadcrosvm-e94b5f84da58d7f74a2c093143b665699c1bebca.tar
crosvm-e94b5f84da58d7f74a2c093143b665699c1bebca.tar.gz
crosvm-e94b5f84da58d7f74a2c093143b665699c1bebca.tar.bz2
crosvm-e94b5f84da58d7f74a2c093143b665699c1bebca.tar.lz
crosvm-e94b5f84da58d7f74a2c093143b665699c1bebca.tar.xz
crosvm-e94b5f84da58d7f74a2c093143b665699c1bebca.tar.zst
crosvm-e94b5f84da58d7f74a2c093143b665699c1bebca.zip
pci: refactor FDT/MPTABLE creation to use PciAddress.
Simple refactor of FDT and MPTables generation to use PCI device
addressing and allow declatation of non-zero PCI bus ids for x86
architectures. It also allows non sequential IRQ allocation for
PCI devices.

BUG=None
TEST=build_test & tast run crostini.Sanity

Change-Id: I6cc31ce412199a732499b2d8d18d99f08d765690
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2175739
Tested-by: Tomasz Jeznach <tjeznach@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Commit-Queue: Tomasz Jeznach <tjeznach@chromium.org>
Diffstat (limited to 'x86_64')
-rw-r--r--x86_64/src/lib.rs6
-rw-r--r--x86_64/src/mptable.rs39
2 files changed, 24 insertions, 21 deletions
diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs
index 2e54998..a6a02bc 100644
--- a/x86_64/src/lib.rs
+++ b/x86_64/src/lib.rs
@@ -60,7 +60,7 @@ use arch::{
 };
 use devices::split_irqchip_common::GsiRelay;
 use devices::{
-    Ioapic, PciConfigIo, PciDevice, PciInterruptPin, Pic, IOAPIC_BASE_ADDRESS,
+    Ioapic, PciAddress, PciConfigIo, PciDevice, PciInterruptPin, Pic, IOAPIC_BASE_ADDRESS,
     IOAPIC_MEM_LENGTH_BYTES,
 };
 use io_jail::Minijail;
@@ -212,7 +212,7 @@ fn configure_system(
     cmdline_addr: GuestAddress,
     cmdline_size: usize,
     num_cpus: u8,
-    pci_irqs: Vec<(u32, PciInterruptPin)>,
+    pci_irqs: Vec<(PciAddress, u32, PciInterruptPin)>,
     setup_data: Option<GuestAddress>,
     initrd: Option<(GuestAddress, usize)>,
     mut params: boot_params,
@@ -588,7 +588,7 @@ impl X8664arch {
         vcpu_count: u32,
         cmdline: &CStr,
         initrd_file: Option<File>,
-        pci_irqs: Vec<(u32, PciInterruptPin)>,
+        pci_irqs: Vec<(PciAddress, u32, PciInterruptPin)>,
         android_fstab: Option<File>,
         kernel_end: u64,
         params: boot_params,
diff --git a/x86_64/src/mptable.rs b/x86_64/src/mptable.rs
index cac9e58..218f561 100644
--- a/x86_64/src/mptable.rs
+++ b/x86_64/src/mptable.rs
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+use std::convert::TryFrom;
 use std::fmt::{self, Display};
 use std::mem;
 use std::result;
@@ -10,7 +11,7 @@ use std::slice;
 use libc::c_char;
 
 use data_model::VolatileMemory;
-use devices::PciInterruptPin;
+use devices::{PciAddress, PciInterruptPin};
 use sys_util::{GuestAddress, GuestMemory};
 
 use crate::mpspec::*;
@@ -117,14 +118,16 @@ fn compute_mp_size(num_cpus: u8) -> usize {
 pub fn setup_mptable(
     mem: &GuestMemory,
     num_cpus: u8,
-    pci_irqs: Vec<(u32, PciInterruptPin)>,
+    pci_irqs: Vec<(PciAddress, u32, PciInterruptPin)>,
 ) -> Result<()> {
-    const PCI_BUS_ID: u8 = 0;
-    const ISA_BUS_ID: u8 = 1;
-
     // Used to keep track of the next base pointer into the MP table.
     let mut base_mp = GuestAddress(MPTABLE_START);
 
+    // Calculate ISA bus number in the system, report at least one PCI bus.
+    let isa_bus_id = match pci_irqs.iter().max_by_key(|v| v.0.bus) {
+        Some(pci_irq) => pci_irq.0.bus + 1,
+        _ => 1,
+    };
     let mp_size = compute_mp_size(num_cpus);
 
     // The checked_add here ensures the all of the following base_mp.unchecked_add's will be without
@@ -194,11 +197,11 @@ pub fn setup_mptable(
         base_mp = base_mp.unchecked_add(size as u64);
         checksum = checksum.wrapping_add(compute_checksum(&mpc_ioapic));
     }
-    {
+    for pci_bus_id in 0..isa_bus_id {
         let size = mem::size_of::<mpc_bus>();
         let mut mpc_bus = mpc_bus::default();
         mpc_bus.type_ = MP_BUS as u8;
-        mpc_bus.busid = PCI_BUS_ID;
+        mpc_bus.busid = pci_bus_id;
         mpc_bus.bustype = BUS_TYPE_PCI;
         mem.write_obj_at_addr(mpc_bus, base_mp)
             .map_err(|_| Error::WriteMpcBus)?;
@@ -209,7 +212,7 @@ pub fn setup_mptable(
         let size = mem::size_of::<mpc_bus>();
         let mut mpc_bus = mpc_bus::default();
         mpc_bus.type_ = MP_BUS as u8;
-        mpc_bus.busid = ISA_BUS_ID;
+        mpc_bus.busid = isa_bus_id;
         mpc_bus.bustype = BUS_TYPE_ISA;
         mem.write_obj_at_addr(mpc_bus, base_mp)
             .map_err(|_| Error::WriteMpcBus)?;
@@ -222,7 +225,7 @@ pub fn setup_mptable(
         mpc_intsrc.type_ = MP_INTSRC as u8;
         mpc_intsrc.irqtype = mp_irq_source_types_mp_INT as u8;
         mpc_intsrc.irqflag = MP_IRQDIR_DEFAULT as u16;
-        mpc_intsrc.srcbus = ISA_BUS_ID;
+        mpc_intsrc.srcbus = isa_bus_id;
         mpc_intsrc.srcbusirq = 0;
         mpc_intsrc.dstapic = 0;
         mpc_intsrc.dstirq = 0;
@@ -239,7 +242,7 @@ pub fn setup_mptable(
         mpc_intsrc.type_ = MP_INTSRC as u8;
         mpc_intsrc.irqtype = mp_irq_source_types_mp_INT as u8;
         mpc_intsrc.irqflag = MP_IRQDIR_DEFAULT as u16;
-        mpc_intsrc.srcbus = ISA_BUS_ID;
+        mpc_intsrc.srcbus = isa_bus_id;
         mpc_intsrc.srcbusirq = i;
         mpc_intsrc.dstapic = ioapicid;
         mpc_intsrc.dstirq = i;
@@ -257,7 +260,7 @@ pub fn setup_mptable(
         mpc_intsrc.type_ = MP_INTSRC as u8;
         mpc_intsrc.irqtype = mp_irq_source_types_mp_INT as u8;
         mpc_intsrc.irqflag = (MP_IRQDIR_HIGH | MP_LEVEL_TRIGGER) as u16;
-        mpc_intsrc.srcbus = ISA_BUS_ID;
+        mpc_intsrc.srcbus = isa_bus_id;
         mpc_intsrc.srcbusirq = sci_irq;
         mpc_intsrc.dstapic = ioapicid;
         mpc_intsrc.dstirq = sci_irq;
@@ -268,16 +271,16 @@ pub fn setup_mptable(
     }
     let pci_irq_base = super::X86_64_IRQ_BASE as u8;
     // Insert PCI interrupts after platform IRQs.
-    for (i, pci_irq) in pci_irqs.iter().enumerate() {
+    for (address, irq_num, irq_pin) in pci_irqs.iter() {
         let size = mem::size_of::<mpc_intsrc>();
         let mut mpc_intsrc = mpc_intsrc::default();
         mpc_intsrc.type_ = MP_INTSRC as u8;
         mpc_intsrc.irqtype = mp_irq_source_types_mp_INT as u8;
         mpc_intsrc.irqflag = MP_IRQDIR_DEFAULT as u16;
-        mpc_intsrc.srcbus = PCI_BUS_ID;
-        mpc_intsrc.srcbusirq = (pci_irq.0 as u8 + 1) << 2 | pci_irq.1.to_mask() as u8;
+        mpc_intsrc.srcbus = address.bus;
+        mpc_intsrc.srcbusirq = address.dev << 2 | irq_pin.to_mask() as u8;
         mpc_intsrc.dstapic = ioapicid;
-        mpc_intsrc.dstirq = pci_irq_base + i as u8;
+        mpc_intsrc.dstirq = u8::try_from(*irq_num).map_err(|_| Error::WriteMpcIntsrc)?;
         mem.write_obj_at_addr(mpc_intsrc, base_mp)
             .map_err(|_| Error::WriteMpcIntsrc)?;
         base_mp = base_mp.unchecked_add(size as u64);
@@ -290,7 +293,7 @@ pub fn setup_mptable(
         mpc_intsrc.type_ = MP_INTSRC as u8;
         mpc_intsrc.irqtype = mp_irq_source_types_mp_INT as u8;
         mpc_intsrc.irqflag = MP_IRQDIR_DEFAULT as u16;
-        mpc_intsrc.srcbus = ISA_BUS_ID;
+        mpc_intsrc.srcbus = isa_bus_id;
         mpc_intsrc.srcbusirq = i as u8;
         mpc_intsrc.dstapic = ioapicid;
         mpc_intsrc.dstirq = i as u8;
@@ -305,7 +308,7 @@ pub fn setup_mptable(
         mpc_lintsrc.type_ = MP_LINTSRC as u8;
         mpc_lintsrc.irqtype = mp_irq_source_types_mp_ExtINT as u8;
         mpc_lintsrc.irqflag = MP_IRQDIR_DEFAULT as u16;
-        mpc_lintsrc.srcbusid = ISA_BUS_ID;
+        mpc_lintsrc.srcbusid = isa_bus_id;
         mpc_lintsrc.srcbusirq = 0;
         mpc_lintsrc.destapic = 0;
         mpc_lintsrc.destapiclint = 0;
@@ -320,7 +323,7 @@ pub fn setup_mptable(
         mpc_lintsrc.type_ = MP_LINTSRC as u8;
         mpc_lintsrc.irqtype = mp_irq_source_types_mp_NMI as u8;
         mpc_lintsrc.irqflag = MP_IRQDIR_DEFAULT as u16;
-        mpc_lintsrc.srcbusid = ISA_BUS_ID;
+        mpc_lintsrc.srcbusid = isa_bus_id;
         mpc_lintsrc.srcbusirq = 0;
         mpc_lintsrc.destapic = 0xFF; // Per SeaBIOS
         mpc_lintsrc.destapiclint = 1;