Check SAGAW before enabling DMA remapping

This commit is contained in:
Ruihan Li 2025-05-20 12:15:18 +08:00 committed by Junyang Zhang
parent 79b3f68892
commit d2ff5fc1a9
3 changed files with 49 additions and 25 deletions

View File

@ -1,13 +1,13 @@
// SPDX-License-Identifier: MPL-2.0
pub use context_table::RootTable;
use log::info;
use log::{info, warn};
use second_stage::{DeviceMode, PageTableEntry, PagingConsts};
use spin::Once;
use super::IommuError;
use crate::{
arch::iommu::registers::IOMMU_REGS,
arch::iommu::registers::{CapabilitySagaw, IOMMU_REGS},
bus::pci::PciDeviceLocation,
mm::{Daddr, PageTable},
prelude::Paddr,
@ -59,16 +59,28 @@ pub fn unmap(daddr: Daddr) -> Result<(), IommuError> {
}
pub fn init() {
// Create Root Table instance
if !IOMMU_REGS
.get()
.unwrap()
.lock()
.read_capability()
.supported_adjusted_guest_address_widths()
.contains(CapabilitySagaw::AGAW_39BIT_3LP)
{
warn!("[IOMMU] 3-level page tables not supported, disabling DMA remapping");
return;
}
// Create a Root Table instance.
let mut root_table = RootTable::new();
// For all PCI Device, use the same page table.
// For all PCI devices, use the same page table.
let page_table = PageTable::<DeviceMode, PageTableEntry, PagingConsts>::empty();
for table in PciDeviceLocation::all() {
root_table.specify_device_page_table(table, unsafe { page_table.shallow_copy() })
}
PAGE_TABLE.call_once(|| SpinLock::new(root_table));
// Enable DMA remapping
// Enable DMA remapping.
let mut iommu_regs = IOMMU_REGS.get().unwrap().lock();
iommu_regs.enable_dma_remapping(PAGE_TABLE.get().unwrap());
info!("[IOMMU] DMA remapping enabled");

View File

@ -38,7 +38,7 @@ impl Capability {
/// Number of domain support.
///
/// ```norun
/// ```text
/// 0 => 4-bit domain-ids with support for up to 16 domains.
/// 1 => 6-bit domain-ids with support for up to 64 domains.
/// 2 => 8-bit domain-ids with support for up to 256 domains.
@ -54,15 +54,8 @@ impl Capability {
}
/// Supported Adjusted Guest Address Widths.
/// ```norun
/// 0/4 => Reserved
/// 1 => 39-bit AGAW (3-level page-table)
/// 2 => 48-bit AGAW (4-level page-table)
/// 3 => 57-bit AGAW (5-level page-table)
/// ```
pub const fn supported_adjusted_guest_address_widths(&self) -> u64 {
const SAGAW_MASK: u64 = 0x1F << 8;
(self.0 & SAGAW_MASK) >> 8
pub const fn supported_adjusted_guest_address_widths(&self) -> CapabilitySagaw {
CapabilitySagaw::from_bits_truncate(self.0 >> 8)
}
/// Fault-recording Register offset, specifies the offset of the first fault recording
@ -74,15 +67,10 @@ impl Capability {
const FRO_MASK: u64 = 0x3FF << 24;
(self.0 & FRO_MASK) >> 24
}
/// Second Stage Large Page Support.
/// ```norun
/// 2/3 => Reserved
/// 0 => 21-bit offset to page frame(2MB)
/// 1 => 30-bit offset to page frame(1GB)
/// ```
pub const fn second_stage_large_page_support(&self) -> u64 {
const SSLPS_MASK: u64 = 0xF << 34;
(self.0 & SSLPS_MASK) >> 34
pub const fn second_stage_large_page_support(&self) -> CapabilitySslps {
CapabilitySslps::from_bits_truncate(self.0 >> 34)
}
/// Maximum Guest Address Width. The maximum guest physical address width supported
@ -127,7 +115,7 @@ impl Debug for Capability {
bitflags! {
/// Capability flags in IOMMU.
pub struct CapabilityFlags: u64{
pub struct CapabilityFlags: u64 {
/// Required Write-Buffer Flushing.
const RWBF = 1 << 4;
/// Protected Low-Memory Region
@ -160,3 +148,27 @@ bitflags! {
const ESRTPS = 1 << 63;
}
}
bitflags! {
/// Supported Adjusted Guest Address Widths (SAGAW) in IOMMU.
pub struct CapabilitySagaw: u64 {
/// 39-bit AGAW (3-level page-table).
const AGAW_39BIT_3LP = 1 << 1;
/// 48-bit AGAW (4-level page-table).
const AGAW_48BIT_4LP = 1 << 2;
/// 57-bit AGAW (5-level page-table).
const AGAW_57BIT_5LP = 1 << 3;
// 0th and 4th bits are reserved.
}
}
bitflags! {
/// Second Stage Large Page Support (SSLPS) in IOMMU.
pub struct CapabilitySslps: u64 {
/// 21-bit offset to page frame (2MB).
const PAGE_21BIT_2MB = 1 << 0;
/// 30-bit offset to page frame (1GB).
const PAGE_30BIT_1GB = 1 << 1;
// 2nd and 3rd bits are reserved.
}
}

View File

@ -11,7 +11,7 @@ mod status;
use core::ptr::NonNull;
use bit_field::BitField;
pub use capability::Capability;
pub use capability::{Capability, CapabilitySagaw};
use command::GlobalCommand;
use extended_cap::ExtendedCapability;
pub use extended_cap::ExtendedCapabilityFlags;