diff --git a/arch/src/riscv64/layout.rs b/arch/src/riscv64/layout.rs index 3ef7eddf2..0b9de1bc5 100644 --- a/arch/src/riscv64/layout.rs +++ b/arch/src/riscv64/layout.rs @@ -98,7 +98,12 @@ pub const CMDLINE_MAX_SIZE: usize = 1024; pub const FDT_START: GuestAddress = RAM_START; pub const FDT_MAX_SIZE: u64 = 0x1_0000; -/// Kernel start after FDT +/// Put ACPI table above dtb +pub const ACPI_START: GuestAddress = GuestAddress(RAM_START.0 + FDT_MAX_SIZE); +pub const ACPI_MAX_SIZE: u64 = 0x20_0000; +pub const RSDP_POINTER: GuestAddress = ACPI_START; + +/// Kernel start after FDT and ACPI pub const KERNEL_START: GuestAddress = GuestAddress(RAM_START.0 + FDT_MAX_SIZE); /// Pci high memory base diff --git a/arch/src/riscv64/mod.rs b/arch/src/riscv64/mod.rs index 6a0342b3c..e6d70d38a 100644 --- a/arch/src/riscv64/mod.rs +++ b/arch/src/riscv64/mod.rs @@ -22,6 +22,11 @@ use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic}; pub use self::fdt::DeviceInfoForFdt; use crate::{DeviceType, GuestMemoryMmap, PciSpaceInfo, RegionType}; +pub const CLOUDHV_IRQCHIP_NUM_MSIS: u16 = 255; +pub const CLOUDHV_IRQCHIP_NUM_SOURCES: u8 = 96; +pub const CLOUDHV_IRQCHIP_NUM_PRIO_BITS: u8 = 3; +pub const CLOUDHV_IRQCHIP_MAX_GUESTS_BITS: u8 = 3; +pub const CLOUDHV_IRQCHIP_MAX_GUESTS: u8 = (1 << CLOUDHV_IRQCHIP_MAX_GUESTS_BITS) - 1; pub const _NSIG: i32 = 65; /// Errors thrown while configuring riscv64 system. diff --git a/vmm/src/acpi.rs b/vmm/src/acpi.rs index 5a8ab2580..fa107d037 100644 --- a/vmm/src/acpi.rs +++ b/vmm/src/acpi.rs @@ -44,6 +44,10 @@ pub const ACPI_APIC_GIC_MSI_FRAME: u8 = 13; pub const ACPI_APIC_GENERIC_REDISTRIBUTOR: u8 = 14; #[cfg(target_arch = "aarch64")] pub const ACPI_APIC_GENERIC_TRANSLATOR: u8 = 15; +#[cfg(target_arch = "riscv64")] +pub const ACPI_RISC_V_IMSIC: u8 = 0x19; +#[cfg(target_arch = "riscv64")] +pub const ACPI_RISC_V_APLIC: u8 = 0x1A; #[allow(dead_code)] #[repr(C, packed)] diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index 01a51f152..a6d1f4260 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -21,7 +21,6 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Barrier, Mutex}; use std::{cmp, io, result, thread}; -#[cfg(not(target_arch = "riscv64"))] use acpi_tables::sdt::Sdt; use acpi_tables::{Aml, aml}; use anyhow::anyhow; @@ -330,6 +329,47 @@ struct ProcessorHierarchyNode { pub num_private_resources: u32, } +#[cfg(target_arch = "riscv64")] +#[allow(dead_code)] +#[repr(C, packed)] +#[derive(IntoBytes, Immutable, FromBytes)] +struct Imsic { + pub r#type: u8, + pub length: u8, + pub version: u8, + pub reserved: u8, + pub flags: u32, + /// Number of supervisor mode Interrupt Identities + pub n_supervisor_int_id: u16, + /// Number of guest mode Interrupt Identities + pub n_guest_int_id: u16, + pub geust_index_bits: u8, + pub hart_index_bits: u8, + pub group_index_bits: u8, + pub group_index_shift: u8, +} + +#[cfg(target_arch = "riscv64")] +#[allow(dead_code)] +#[repr(C, packed)] +#[derive(IntoBytes, Immutable, FromBytes)] +struct Aplic { + pub r#type: u8, + pub length: u8, + pub version: u8, + pub aplic_id: u8, + pub flags: u32, + pub hardware_id: u64, + /// Number of Interrupt Delivery Control (IDC) structures + pub n_idc: u16, + /// Total External Interrupt Sources Supported + pub n_external_inc_sources: u16, + /// Global System Interrupt Base + pub gsi_inc_base: u32, + pub aplic_addr: u64, + pub aplic_size: u32, +} + #[allow(dead_code)] #[repr(C, packed)] #[derive(Default, IntoBytes, Immutable, FromBytes)] @@ -1487,7 +1527,6 @@ impl CpuManager { }) } - #[cfg(not(target_arch = "riscv64"))] pub fn create_madt(&self, #[cfg(target_arch = "aarch64")] vgic: Arc>) -> Sdt { use crate::acpi; // This is also checked in the commandline parsing. @@ -1633,6 +1672,55 @@ impl CpuManager { madt.update_checksum(); } + #[cfg(target_arch = "riscv64")] + { + /* Notes: + * Ignore Local Interrupt Controller Address at byte offset 36 of MADT table. + */ + + let mut hart_index_bits = 0; + while (1 << hart_index_bits) < self.config.boot_vcpus { + hart_index_bits += 1; + } + + // See section 5.2.12.28. RISC-V Incoming MSI Controller (IMSIC) + // Structure in ACPI spec. + let imsic = Imsic { + r#type: acpi::ACPI_RISC_V_IMSIC, + length: 16, + version: 1, + reserved: 0, + flags: 0, + n_supervisor_int_id: arch::riscv64::CLOUDHV_IRQCHIP_NUM_MSIS, + n_guest_int_id: arch::riscv64::CLOUDHV_IRQCHIP_NUM_MSIS, + geust_index_bits: 1, + hart_index_bits: hart_index_bits, + group_index_bits: 1, + // IMSIC_MMIO_GROUP_MIN_SHIFT + group_index_shift: 24, + }; + madt.append(imsic); + + // See section 5.2.12.29. RISC-V Advanced Platform Level Interrupt + // Controller (APLIC) Structure in ACPI spec. + let aplic = Aplic { + r#type: acpi::ACPI_RISC_V_APLIC, + length: 36, + version: 1, + aplic_id: 0, + flags: 0, + hardware_id: 0, + n_idc: 0, + n_external_inc_sources: arch::riscv64::CLOUDHV_IRQCHIP_NUM_SOURCES as u16, + gsi_inc_base: arch::layout::IRQ_BASE, + aplic_addr: arch::layout::APLIC_START.0, + aplic_size: arch::layout::APLIC_SIZE as u32, + }; + madt.append(aplic); + + madt.update_checksum(); + } + madt } diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 992133f7a..4b04ee8eb 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -22,7 +22,6 @@ use std::sync::{Arc, Mutex}; use std::time::Instant; use acpi_tables::sdt::GenericAddress; -#[cfg(not(target_arch = "riscv64"))] use acpi_tables::{Aml, aml}; #[cfg(not(target_arch = "riscv64"))] use anyhow::anyhow; @@ -1043,7 +1042,6 @@ pub struct DeviceManager { // activation and thus start the threads from the VMM thread activate_evt: EventFd, - #[cfg(not(target_arch = "riscv64"))] acpi_address: GuestAddress, selected_segment: usize, @@ -1083,7 +1081,6 @@ pub struct DeviceManager { // Pending activations pending_activations: Arc>>, - #[cfg(not(target_arch = "riscv64"))] // Addresses for ACPI platform devices e.g. ACPI PM timer, sleep/reset registers acpi_platform_addresses: AcpiPlatformAddresses, @@ -1339,7 +1336,6 @@ impl DeviceManager { activate_evt: activate_evt .try_clone() .map_err(DeviceManagerError::EventFd)?, - #[cfg(not(target_arch = "riscv64"))] acpi_address, selected_segment: 0, serial_manager: None, @@ -1358,7 +1354,6 @@ impl DeviceManager { #[cfg(not(target_arch = "riscv64"))] timestamp, pending_activations: Arc::new(Mutex::new(Vec::default())), - #[cfg(not(target_arch = "riscv64"))] acpi_platform_addresses: AcpiPlatformAddresses::default(), snapshot, rate_limit_groups, @@ -4961,7 +4956,6 @@ impl DeviceManager { Ok(()) } - #[cfg(not(target_arch = "riscv64"))] pub(crate) fn acpi_platform_addresses(&self) -> &AcpiPlatformAddresses { &self.acpi_platform_addresses } @@ -5088,11 +5082,12 @@ impl Aml for TpmDevice { } } -#[cfg(not(target_arch = "riscv64"))] impl Aml for DeviceManager { fn to_aml_bytes(&self, sink: &mut dyn acpi_tables::AmlSink) { #[cfg(target_arch = "aarch64")] use arch::aarch64::DeviceInfoForFdt; + #[cfg(target_arch = "riscv64")] + use arch::riscv64::DeviceInfoForFdt; let mut pci_scan_methods = Vec::new(); for i in 0..self.pci_segments.len() { @@ -5218,7 +5213,7 @@ impl Aml for DeviceManager { // Serial device #[cfg(target_arch = "x86_64")] let serial_irq = 4; - #[cfg(target_arch = "aarch64")] + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] let serial_irq = if self.config.lock().unwrap().serial.clone().mode != ConsoleOutputMode::Off { self.get_device_info() @@ -5240,6 +5235,8 @@ impl Aml for DeviceManager { &aml::EISAName::new("PNP0501"), #[cfg(target_arch = "aarch64")] &"ARMH0011", + #[cfg(target_arch = "riscv64")] + &"RISCV011", ), &aml::Name::new("_UID".into(), &aml::ZERO), &aml::Name::new("_DDN".into(), &"COM1"), @@ -5273,6 +5270,7 @@ impl Aml for DeviceManager { ) .to_aml_bytes(sink); + #[cfg(not(target_arch = "riscv64"))] if self.config.lock().unwrap().tpm.is_some() { // Add tpm device TpmDevice {}.to_aml_bytes(sink); diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index a16c2480f..bac3b3e13 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -67,7 +67,6 @@ use crate::vm_config::{ VmConfig, VsockConfig, }; -#[cfg(not(target_arch = "riscv64"))] mod acpi; pub mod api; mod clone3;