summary refs log tree commit diff
path: root/x86_64
diff options
context:
space:
mode:
Diffstat (limited to 'x86_64')
-rw-r--r--x86_64/src/gdt.rs8
-rw-r--r--x86_64/src/interrupts.rs2
-rw-r--r--x86_64/src/lib.rs20
-rw-r--r--x86_64/src/mpspec.rs1
-rw-r--r--x86_64/src/mptable.rs26
5 files changed, 40 insertions, 17 deletions
diff --git a/x86_64/src/gdt.rs b/x86_64/src/gdt.rs
index 7eb1ff7..a37ddd4 100644
--- a/x86_64/src/gdt.rs
+++ b/x86_64/src/gdt.rs
@@ -8,17 +8,17 @@ use kvm_sys::kvm_segment;
 
 /// Constructor for a conventional segment GDT (or LDT) entry. Derived from the kernel's segment.h.
 pub fn gdt_entry(flags: u16, base: u32, limit: u32) -> u64 {
-    ((((base as u64) & 0xff000000u64) << (56 - 24))
+    (((base as u64) & 0xff000000u64) << (56 - 24))
         | (((flags as u64) & 0x0000f0ffu64) << 40)
         | (((limit as u64) & 0x000f0000u64) << (48 - 16))
         | (((base as u64) & 0x00ffffffu64) << 16)
-        | ((limit as u64) & 0x0000ffffu64))
+        | ((limit as u64) & 0x0000ffffu64)
 }
 
 fn get_base(entry: u64) -> u64 {
-    ((((entry) & 0xFF00000000000000) >> 32)
+    (((entry) & 0xFF00000000000000) >> 32)
         | (((entry) & 0x000000FF00000000) >> 16)
-        | (((entry) & 0x00000000FFFF0000) >> 16))
+        | (((entry) & 0x00000000FFFF0000) >> 16)
 }
 
 fn get_limit(entry: u64) -> u32 {
diff --git a/x86_64/src/interrupts.rs b/x86_64/src/interrupts.rs
index a2b0f1c..5fba859 100644
--- a/x86_64/src/interrupts.rs
+++ b/x86_64/src/interrupts.rs
@@ -57,7 +57,7 @@ fn set_klapic_reg(klapic: &mut kvm_lapic_state, reg_offset: usize, value: u32) {
 }
 
 fn set_apic_delivery_mode(reg: u32, mode: u32) -> u32 {
-    (((reg) & !0x700) | ((mode) << 8))
+    ((reg) & !0x700) | ((mode) << 8)
 }
 
 /// Configures LAPICs.  LAPIC0 is set for external interrupts, LAPIC1 is set for NMI.
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;