aarch64: Fix IRQ number setting for ACPI

On FDT, VMM can allocate IRQ from 0 for devices.
But on ACPI, the lowest range below 32 has to be avoided.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
Michael Zhao 2021-03-23 19:41:36 +08:00 committed by Sebastien Boeuf
parent efc583c13e
commit ff46fb69d0
9 changed files with 35 additions and 18 deletions

View File

@ -16,7 +16,7 @@ use super::super::InitramfsConfig;
use super::get_fdt_addr;
use super::gic::GicDevice;
use super::layout::{
FDT_MAX_SIZE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, PCI_MMCONFIG_SIZE,
FDT_MAX_SIZE, IRQ_BASE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, PCI_MMCONFIG_SIZE,
PCI_MMCONFIG_START,
};
use vm_fdt::{FdtWriter, FdtWriterResult};
@ -293,7 +293,11 @@ fn create_serial_node<T: DeviceInfoForFdt + Clone + Debug>(
) -> FdtWriterResult<()> {
let compatible = b"arm,pl011\0arm,primecell\0";
let serial_reg_prop = [dev_info.addr(), dev_info.length()];
let irq = [GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING];
let irq = [
GIC_FDT_IRQ_TYPE_SPI,
dev_info.irq() - IRQ_BASE,
IRQ_TYPE_EDGE_RISING,
];
let serial_node = fdt.begin_node(&format!("pl011@{:x}", dev_info.addr()))?;
fdt.property("compatible", compatible)?;
@ -312,7 +316,11 @@ fn create_rtc_node<T: DeviceInfoForFdt + Clone + Debug>(
) -> FdtWriterResult<()> {
let compatible = b"arm,pl031\0arm,primecell\0";
let rtc_reg_prop = [dev_info.addr(), dev_info.length()];
let irq = [GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_LEVEL_HI];
let irq = [
GIC_FDT_IRQ_TYPE_SPI,
dev_info.irq() - IRQ_BASE,
IRQ_TYPE_LEVEL_HI,
];
let rtc_node = fdt.begin_node(&format!("rtc@{:x}", dev_info.addr()))?;
fdt.property("compatible", compatible)?;
@ -332,7 +340,11 @@ fn create_gpio_node<T: DeviceInfoForFdt + Clone + Debug>(
// PL061 GPIO controller node
let compatible = b"arm,pl061\0arm,primecell\0";
let gpio_reg_prop = [dev_info.addr(), dev_info.length()];
let irq = [GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING];
let irq = [
GIC_FDT_IRQ_TYPE_SPI,
dev_info.irq() - IRQ_BASE,
IRQ_TYPE_EDGE_RISING,
];
let gpio_node = fdt.begin_node(&format!("pl061@{:x}", dev_info.addr()))?;
fdt.property("compatible", compatible)?;

View File

@ -149,7 +149,7 @@ pub mod kvm {
/* We need to tell the kernel how many irqs to support with this vgic.
* See the `layout` module for details.
*/
let nr_irqs: u32 = layout::IRQ_MAX - layout::IRQ_BASE + 1;
let nr_irqs: u32 = layout::IRQ_NUM;
let nr_irqs_ptr = &nr_irqs as *const u32;
Self::set_device_attribute(
gic_device.device(),

View File

@ -97,8 +97,8 @@ pub const KERNEL_START: u64 = ACPI_START + ACPI_MAX_SIZE as u64;
// * less than 1023 and
// * a multiple of 32.
// We are setting up our interrupt controller to support a maximum of 256 interrupts.
/// First usable interrupt on aarch64.
pub const IRQ_BASE: u32 = 0;
/// First usable interrupt on aarch64
pub const IRQ_BASE: u32 = 32;
/// Last usable interrupt on aarch64.
pub const IRQ_MAX: u32 = 255;
/// Number of supported interrupts
pub const IRQ_NUM: u32 = 256;

View File

@ -76,7 +76,7 @@ pub mod aarch64;
pub use aarch64::{
arch_memory_regions, configure_system, configure_vcpu, fdt::DeviceInfoForFdt,
get_host_cpu_phys_bits, get_kernel_start, initramfs_load_addr, layout,
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, layout::IRQ_MAX, EntryPoint,
layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE, EntryPoint,
};
#[cfg(target_arch = "x86_64")]

View File

@ -7,6 +7,7 @@ edition = "2018"
[dependencies]
acpi_tables = { path = "../acpi_tables", optional = true }
anyhow = "1.0"
arch = { path = "../arch" }
bitflags = ">=1.2.1"
byteorder = "1.4.3"
epoll = ">=4.0.1"

View File

@ -3,6 +3,7 @@
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use super::interrupt_controller::{Error, InterruptController};
extern crate arch;
use std::result;
use std::sync::Arc;
use vm_device::interrupt::{
@ -14,7 +15,7 @@ use vmm_sys_util::eventfd::EventFd;
type Result<T> = result::Result<T, Error>;
// Reserve 32 IRQs for legacy device.
pub const IRQ_LEGACY_BASE: usize = 0;
pub const IRQ_LEGACY_BASE: usize = arch::layout::IRQ_BASE as usize;
pub const IRQ_LEGACY_COUNT: usize = 32;
// This Gic struct implements InterruptController to provide interrupt delivery service.
@ -58,7 +59,7 @@ impl InterruptController for Gic {
for i in IRQ_LEGACY_BASE..(IRQ_LEGACY_BASE + IRQ_LEGACY_COUNT) {
let config = LegacyIrqSourceConfig {
irqchip: 0,
pin: i as u32,
pin: (i - IRQ_LEGACY_BASE) as u32,
};
self.interrupt_source_group
.update(

View File

@ -42,11 +42,11 @@ fn pagesize() -> usize {
/// #[cfg(target_arch = "x86_64")]
/// assert_eq!(allocator.allocate_irq(), Some(5));
/// #[cfg(target_arch = "aarch64")]
/// assert_eq!(allocator.allocate_irq(), Some(0));
/// assert_eq!(allocator.allocate_irq(), Some(32));
/// #[cfg(target_arch = "x86_64")]
/// assert_eq!(allocator.allocate_irq(), Some(6));
/// #[cfg(target_arch = "aarch64")]
/// assert_eq!(allocator.allocate_irq(), Some(1));
/// assert_eq!(allocator.allocate_irq(), Some(33));
/// assert_eq!(allocator.allocate_mmio_addresses(None, 0x1000, Some(0x1000)), Some(GuestAddress(0x1fff_f000)));
///
/// ```

View File

@ -456,7 +456,7 @@ mod tests {
let res = get_dist_regs(gic.device());
assert!(res.is_ok());
let state = res.unwrap();
assert_eq!(state.len(), 649);
assert_eq!(state.len(), 568);
let res = set_dist_regs(gic.device(), &state);
assert!(res.is_ok());

View File

@ -2425,20 +2425,23 @@ mod tests {
let dev_info: HashMap<(DeviceType, std::string::String), MmioDeviceInfo> = [
(
(DeviceType::Serial, DeviceType::Serial.to_string()),
MmioDeviceInfo { addr: 0x00, irq: 1 },
MmioDeviceInfo {
addr: 0x00,
irq: 33,
},
),
(
(DeviceType::Virtio(1), "virtio".to_string()),
MmioDeviceInfo {
addr: 0x00 + LEN,
irq: 2,
irq: 34,
},
),
(
(DeviceType::Rtc, "rtc".to_string()),
MmioDeviceInfo {
addr: 0x00 + 2 * LEN,
irq: 3,
irq: 35,
},
),
]