diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs index a912eddb59..a4ba444055 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, 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, 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 ab7af51eaa..5340d9e24b 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 9aded3fd0b..cac9e58df3 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::(); 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::(); + 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::(); @@ -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::(); let mut mpc_intsrc = mpc_intsrc::default(); mpc_intsrc.type_ = MP_INTSRC as u8;