summary refs log tree commit diff
path: root/x86_64
diff options
context:
space:
mode:
authorChuanxiao Dong <chuanxiao.dong@intel.corp-partner.google.com>2020-03-10 13:33:09 +0800
committerCommit Bot <commit-bot@chromium.org>2020-03-19 12:11:51 +0000
commit9486e57a097aeb98ccb33776aefa523be795b661 (patch)
tree4027dbf78a598fab15a4c9757137d17d648ab76e /x86_64
parent5b2447ceaf8ec4fa12afa32936af075c61e900df (diff)
downloadcrosvm-9486e57a097aeb98ccb33776aefa523be795b661.tar
crosvm-9486e57a097aeb98ccb33776aefa523be795b661.tar.gz
crosvm-9486e57a097aeb98ccb33776aefa523be795b661.tar.bz2
crosvm-9486e57a097aeb98ccb33776aefa523be795b661.tar.lz
crosvm-9486e57a097aeb98ccb33776aefa523be795b661.tar.xz
crosvm-9486e57a097aeb98ccb33776aefa523be795b661.tar.zst
crosvm-9486e57a097aeb98ccb33776aefa523be795b661.zip
ACPI: enable ACPI from command line
Previously the "acpi=off" in cmdline has disabled the ACPI for the
guest kernel. With removing the "acpi=off", the ACPI will be enabled
for the guest kernel by default. With acpi enabled, the SCI irq will
be needed by the ACPI core driver. Register the SCI irq in MP table
so that it can use IO-APIC routing.

The reason to have "pci=noacpi" is that, in the current DSDT there is
only suspend capability, so PCI scan still need to be done by the
traditional way.

BUG=chromium:1018674
TEST=Linux guest is able to boot up with the virtio devices functional.
Also able to see the S1 capability from kernel dmesg.

Change-Id: Id54e788f4aa4c944fac5e3fa1c92b76865dd5021
Signed-off-by: Chuanxiao Dong <chuanxiao.dong@intel.corp-partner.google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2078967
Reviewed-by: Tomasz Jeznach <tjeznach@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'x86_64')
-rw-r--r--x86_64/src/lib.rs20
-rw-r--r--x86_64/src/mpspec.rs1
-rw-r--r--x86_64/src/mptable.rs26
3 files changed, 35 insertions, 12 deletions
diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs
index a912edd..a4ba444 100644
--- a/x86_64/src/lib.rs
+++ b/x86_64/src/lib.rs
@@ -189,7 +189,15 @@ const CMDLINE_OFFSET: u64 = 0x20000;
 const CMDLINE_MAX_SIZE: u64 = KERNEL_START_OFFSET - CMDLINE_OFFSET;
 const X86_64_SERIAL_1_3_IRQ: u32 = 4;
 const X86_64_SERIAL_2_4_IRQ: u32 = 3;
-const X86_64_IRQ_BASE: u32 = 5;
+// X86_64_SCI_IRQ is used to fill the ACPI FACP table.
+// The sci_irq number is better to be a legacy
+// IRQ number which is less than 16(actually most of the
+// platforms have fixed IRQ number 9). So we can
+// reserve the IRQ number 5 for SCI and let the
+// the other devices starts from next.
+pub const X86_64_SCI_IRQ: u32 = 5;
+// So the IRQ_BASE start from SCI_IRQ + 1
+pub const X86_64_IRQ_BASE: u32 = X86_64_SCI_IRQ + 1;
 const ACPI_HI_RSDP_WINDOW_BASE: u64 = 0x000E0000;
 
 fn configure_system(
@@ -203,7 +211,6 @@ fn configure_system(
     setup_data: Option<GuestAddress>,
     initrd: Option<(GuestAddress, usize)>,
     mut params: boot_params,
-    sci_irq: u32,
 ) -> Result<()> {
     const EBDA_START: u64 = 0x0009fc00;
     const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55;
@@ -267,7 +274,7 @@ fn configure_system(
         .write_obj_at_addr(params, zero_page_addr)
         .map_err(|_| Error::ZeroPageSetup)?;
 
-    let rsdp_addr = acpi::create_acpi_tables(guest_mem, num_cpus, sci_irq);
+    let rsdp_addr = acpi::create_acpi_tables(guest_mem, num_cpus, X86_64_SCI_IRQ);
     params.acpi_rsdp_addr = rsdp_addr.0;
 
     Ok(())
@@ -404,8 +411,6 @@ impl arch::LinuxArch for X8664arch {
 
         // Event used to notify crosvm that guest OS is trying to suspend.
         let suspend_evt = EventFd::new().map_err(Error::CreateEventFd)?;
-        // allocate sci_irq to fill the ACPI FACP table
-        let sci_irq = resources.allocate_irq().ok_or(Error::AllocateIrq)?;
 
         let mut io_bus = Self::setup_io_bus(
             &mut vm,
@@ -492,7 +497,6 @@ impl arch::LinuxArch for X8664arch {
                     components.android_fstab,
                     kernel_end,
                     params,
-                    sci_irq,
                 )?;
             }
         }
@@ -579,7 +583,6 @@ impl X8664arch {
         android_fstab: Option<File>,
         kernel_end: u64,
         params: boot_params,
-        sci_irq: u32,
     ) -> Result<()> {
         kernel_loader::load_cmdline(mem, GuestAddress(CMDLINE_OFFSET), cmdline)
             .map_err(Error::LoadCmdline)?;
@@ -641,7 +644,6 @@ impl X8664arch {
             setup_data,
             initrd,
             params,
-            sci_irq,
         )?;
         Ok(())
     }
@@ -723,7 +725,7 @@ impl X8664arch {
             let tty_string = get_serial_tty_string(stdio_serial_num);
             cmdline.insert("console", &tty_string).unwrap();
         }
-        cmdline.insert_str("acpi=off reboot=k panic=-1").unwrap();
+        cmdline.insert_str("pci=noacpi reboot=k panic=-1").unwrap();
 
         cmdline
     }
diff --git a/x86_64/src/mpspec.rs b/x86_64/src/mpspec.rs
index ab7af51..5340d9e 100644
--- a/x86_64/src/mpspec.rs
+++ b/x86_64/src/mpspec.rs
@@ -38,6 +38,7 @@ pub const MPC_APIC_USABLE: ::std::os::raw::c_uint = 1;
 pub const MP_IRQDIR_DEFAULT: ::std::os::raw::c_uint = 0;
 pub const MP_IRQDIR_HIGH: ::std::os::raw::c_uint = 1;
 pub const MP_IRQDIR_LOW: ::std::os::raw::c_uint = 3;
+pub const MP_LEVEL_TRIGGER: ::std::os::raw::c_uint = 0xc;
 pub const MP_APIC_ALL: ::std::os::raw::c_uint = 255;
 pub const MPC_OEM_SIGNATURE: &'static [u8; 5usize] = b"_OEM\x00";
 #[repr(C)]
diff --git a/x86_64/src/mptable.rs b/x86_64/src/mptable.rs
index 9aded3f..cac9e58 100644
--- a/x86_64/src/mptable.rs
+++ b/x86_64/src/mptable.rs
@@ -231,8 +231,9 @@ pub fn setup_mptable(
         base_mp = base_mp.unchecked_add(size as u64);
         checksum = checksum.wrapping_add(compute_checksum(&mpc_intsrc));
     }
+    let sci_irq = super::X86_64_SCI_IRQ as u8;
     // Per kvm_setup_default_irq_routing() in kernel
-    for i in 0..5 {
+    for i in 0..sci_irq {
         let size = mem::size_of::<mpc_intsrc>();
         let mut mpc_intsrc = mpc_intsrc::default();
         mpc_intsrc.type_ = MP_INTSRC as u8;
@@ -247,6 +248,25 @@ pub fn setup_mptable(
         base_mp = base_mp.unchecked_add(size as u64);
         checksum = checksum.wrapping_add(compute_checksum(&mpc_intsrc));
     }
+    // Insert SCI interrupt before PCI interrupts. Set the SCI interrupt
+    // to be the default trigger/polarity of PCI bus, which is level/low.
+    // This setting can be changed in future if necessary.
+    {
+        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_HIGH | MP_LEVEL_TRIGGER) as u16;
+        mpc_intsrc.srcbus = ISA_BUS_ID;
+        mpc_intsrc.srcbusirq = sci_irq;
+        mpc_intsrc.dstapic = ioapicid;
+        mpc_intsrc.dstirq = sci_irq;
+        mem.write_obj_at_addr(mpc_intsrc, base_mp)
+            .map_err(|_| Error::WriteMpcIntsrc)?;
+        base_mp = base_mp.unchecked_add(size as u64);
+        checksum = checksum.wrapping_add(compute_checksum(&mpc_intsrc));
+    }
+    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() {
         let size = mem::size_of::<mpc_intsrc>();
@@ -257,14 +277,14 @@ pub fn setup_mptable(
         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.dstapic = ioapicid;
-        mpc_intsrc.dstirq = 5 + i as u8;
+        mpc_intsrc.dstirq = pci_irq_base + i as u8;
         mem.write_obj_at_addr(mpc_intsrc, base_mp)
             .map_err(|_| Error::WriteMpcIntsrc)?;
         base_mp = base_mp.unchecked_add(size as u64);
         checksum = checksum.wrapping_add(compute_checksum(&mpc_intsrc));
     }
     // Finally insert ISA interrupts.
-    for i in 5 + pci_irqs.len()..16 {
+    for i in pci_irq_base + pci_irqs.len() as u8..16 {
         let size = mem::size_of::<mpc_intsrc>();
         let mut mpc_intsrc = mpc_intsrc::default();
         mpc_intsrc.type_ = MP_INTSRC as u8;