diff options
Diffstat (limited to 'x86_64')
-rw-r--r-- | x86_64/src/gdt.rs | 8 | ||||
-rw-r--r-- | x86_64/src/interrupts.rs | 2 | ||||
-rw-r--r-- | x86_64/src/lib.rs | 20 | ||||
-rw-r--r-- | x86_64/src/mpspec.rs | 1 | ||||
-rw-r--r-- | x86_64/src/mptable.rs | 26 |
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; |