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>
This commit is contained in:
Chuanxiao Dong 2020-03-10 13:33:09 +08:00 committed by Commit Bot
parent 5b2447ceaf
commit 9486e57a09
3 changed files with 35 additions and 12 deletions

View file

@ -189,7 +189,15 @@ const CMDLINE_OFFSET: u64 = 0x20000;
const CMDLINE_MAX_SIZE: u64 = KERNEL_START_OFFSET - CMDLINE_OFFSET; const CMDLINE_MAX_SIZE: u64 = KERNEL_START_OFFSET - CMDLINE_OFFSET;
const X86_64_SERIAL_1_3_IRQ: u32 = 4; const X86_64_SERIAL_1_3_IRQ: u32 = 4;
const X86_64_SERIAL_2_4_IRQ: u32 = 3; 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; const ACPI_HI_RSDP_WINDOW_BASE: u64 = 0x000E0000;
fn configure_system( fn configure_system(
@ -203,7 +211,6 @@ fn configure_system(
setup_data: Option<GuestAddress>, setup_data: Option<GuestAddress>,
initrd: Option<(GuestAddress, usize)>, initrd: Option<(GuestAddress, usize)>,
mut params: boot_params, mut params: boot_params,
sci_irq: u32,
) -> Result<()> { ) -> Result<()> {
const EBDA_START: u64 = 0x0009fc00; const EBDA_START: u64 = 0x0009fc00;
const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55; const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55;
@ -267,7 +274,7 @@ fn configure_system(
.write_obj_at_addr(params, zero_page_addr) .write_obj_at_addr(params, zero_page_addr)
.map_err(|_| Error::ZeroPageSetup)?; .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; params.acpi_rsdp_addr = rsdp_addr.0;
Ok(()) Ok(())
@ -404,8 +411,6 @@ impl arch::LinuxArch for X8664arch {
// Event used to notify crosvm that guest OS is trying to suspend. // Event used to notify crosvm that guest OS is trying to suspend.
let suspend_evt = EventFd::new().map_err(Error::CreateEventFd)?; 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( let mut io_bus = Self::setup_io_bus(
&mut vm, &mut vm,
@ -492,7 +497,6 @@ impl arch::LinuxArch for X8664arch {
components.android_fstab, components.android_fstab,
kernel_end, kernel_end,
params, params,
sci_irq,
)?; )?;
} }
} }
@ -579,7 +583,6 @@ impl X8664arch {
android_fstab: Option<File>, android_fstab: Option<File>,
kernel_end: u64, kernel_end: u64,
params: boot_params, params: boot_params,
sci_irq: u32,
) -> Result<()> { ) -> Result<()> {
kernel_loader::load_cmdline(mem, GuestAddress(CMDLINE_OFFSET), cmdline) kernel_loader::load_cmdline(mem, GuestAddress(CMDLINE_OFFSET), cmdline)
.map_err(Error::LoadCmdline)?; .map_err(Error::LoadCmdline)?;
@ -641,7 +644,6 @@ impl X8664arch {
setup_data, setup_data,
initrd, initrd,
params, params,
sci_irq,
)?; )?;
Ok(()) Ok(())
} }
@ -723,7 +725,7 @@ impl X8664arch {
let tty_string = get_serial_tty_string(stdio_serial_num); let tty_string = get_serial_tty_string(stdio_serial_num);
cmdline.insert("console", &tty_string).unwrap(); 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 cmdline
} }

View file

@ -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_DEFAULT: ::std::os::raw::c_uint = 0;
pub const MP_IRQDIR_HIGH: ::std::os::raw::c_uint = 1; 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_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 MP_APIC_ALL: ::std::os::raw::c_uint = 255;
pub const MPC_OEM_SIGNATURE: &'static [u8; 5usize] = b"_OEM\x00"; pub const MPC_OEM_SIGNATURE: &'static [u8; 5usize] = b"_OEM\x00";
#[repr(C)] #[repr(C)]

View file

@ -231,8 +231,9 @@ pub fn setup_mptable(
base_mp = base_mp.unchecked_add(size as u64); base_mp = base_mp.unchecked_add(size as u64);
checksum = checksum.wrapping_add(compute_checksum(&mpc_intsrc)); 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 // 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 size = mem::size_of::<mpc_intsrc>();
let mut mpc_intsrc = mpc_intsrc::default(); let mut mpc_intsrc = mpc_intsrc::default();
mpc_intsrc.type_ = MP_INTSRC as u8; mpc_intsrc.type_ = MP_INTSRC as u8;
@ -247,6 +248,25 @@ pub fn setup_mptable(
base_mp = base_mp.unchecked_add(size as u64); base_mp = base_mp.unchecked_add(size as u64);
checksum = checksum.wrapping_add(compute_checksum(&mpc_intsrc)); 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. // Insert PCI interrupts after platform IRQs.
for (i, pci_irq) in pci_irqs.iter().enumerate() { for (i, pci_irq) in pci_irqs.iter().enumerate() {
let size = mem::size_of::<mpc_intsrc>(); let size = mem::size_of::<mpc_intsrc>();
@ -257,14 +277,14 @@ pub fn setup_mptable(
mpc_intsrc.srcbus = PCI_BUS_ID; 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.srcbusirq = (pci_irq.0 as u8 + 1) << 2 | pci_irq.1.to_mask() as u8;
mpc_intsrc.dstapic = ioapicid; 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) mem.write_obj_at_addr(mpc_intsrc, base_mp)
.map_err(|_| Error::WriteMpcIntsrc)?; .map_err(|_| Error::WriteMpcIntsrc)?;
base_mp = base_mp.unchecked_add(size as u64); base_mp = base_mp.unchecked_add(size as u64);
checksum = checksum.wrapping_add(compute_checksum(&mpc_intsrc)); checksum = checksum.wrapping_add(compute_checksum(&mpc_intsrc));
} }
// Finally insert ISA interrupts. // 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 size = mem::size_of::<mpc_intsrc>();
let mut mpc_intsrc = mpc_intsrc::default(); let mut mpc_intsrc = mpc_intsrc::default();
mpc_intsrc.type_ = MP_INTSRC as u8; mpc_intsrc.type_ = MP_INTSRC as u8;