From 63b42bff732a323a4e739063bb19e9e3a569881c Mon Sep 17 00:00:00 2001 From: Yuke Peng Date: Thu, 18 Jul 2024 20:40:46 +0800 Subject: [PATCH] Add register descriptions --- .../arch/x86/iommu/registers/capability.rs | 162 ++++++++++++++++++ ostd/src/arch/x86/iommu/registers/command.rs | 56 ++++++ .../arch/x86/iommu/registers/extended_cap.rs | 123 +++++++++++++ ostd/src/arch/x86/iommu/registers/status.rs | 54 ++++++ 4 files changed, 395 insertions(+) create mode 100644 ostd/src/arch/x86/iommu/registers/capability.rs create mode 100644 ostd/src/arch/x86/iommu/registers/command.rs create mode 100644 ostd/src/arch/x86/iommu/registers/extended_cap.rs create mode 100644 ostd/src/arch/x86/iommu/registers/status.rs diff --git a/ostd/src/arch/x86/iommu/registers/capability.rs b/ostd/src/arch/x86/iommu/registers/capability.rs new file mode 100644 index 000000000..c6b3a33e7 --- /dev/null +++ b/ostd/src/arch/x86/iommu/registers/capability.rs @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: MPL-2.0 + +use core::fmt::Debug; + +use bitflags::bitflags; + +/// Capability in IOMMU. +pub struct Capability(u64); + +impl Capability { + /// Create Capability from `value` + pub const fn new(value: u64) -> Self { + Self(value) + } + + /// Capability flags + pub const fn flags(&self) -> CapabilityFlags { + CapabilityFlags::from_bits_truncate(self.0) + } + + /// Number of Fault-recording. The maximum number of fault recording registers per + /// remapping hardware unit is 256. + /// + /// Number of fault recording registers is computed as N+1, where N is the value + /// reported in this field. + pub const fn fault_recording_number(&self) -> u64 { + const NFR_MASK: u64 = 0xFF << 40; + (self.0 & NFR_MASK) >> 40 + } + + /// Maximum Address Mask Value, indicates the maximum supported value for them Address + /// Mask (AM) field in the Invalidation Address register (IVA_REG), and IOTLB Invalidation + /// Descriptor (iotlb_inv_dsc) used for invalidations of second-stage translation. + pub const fn maximum_address_mask_value(&self) -> u64 { + const MAMV_MASK: u64 = 0x3F << 48; + (self.0 & MAMV_MASK) >> 48 + } + + /// Number of domain support. + /// + /// ```norun + /// 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. + /// 3 => 10-bit domain-ids with support for up to 1024 domains. + /// 4 => 12-bit domain-ids with support for up to 4K domains. + /// 5 => 14-bit domain-ids with support for up to 16K domains. + /// 6 => 16-bit domain-ids with support for up to 64K domains. + /// 7 => Reserved. + /// ``` + pub const fn domain_support_number(&self) -> u64 { + const ND_MASK: u64 = 0x7; + self.0 & ND_MASK + } + + /// 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 + } + + /// Fault-recording Register offset, specifies the offset of the first fault recording + /// register relative to the register base address of this remapping hardware unit. + /// + /// If the register base address is X, and the value reported in this field + /// is Y, the address for the first fault recording register is calculated as X+(16*Y). + pub const fn fault_recording_register_offset(&self) -> u64 { + const FRO_MASK: u64 = 0x3FFF << 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 + } + + /// Maximum Guest Address Width. The maximum guest physical address width supported + /// by second-stage translation in remapping hardware. + /// MGAW is computed as (N+1), where N is the valued reported in this field. + pub const fn maximum_guest_address_width(&self) -> u64 { + const MGAW_MASK: u64 = 0x3F << 16; + (self.0 & MGAW_MASK) >> 16 + } +} + +impl Debug for Capability { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Capability") + .field("flags", &self.flags()) + .field( + "maximum_guest_address_width", + &self.maximum_guest_address_width(), + ) + .field( + "second_stage_large_page_support", + &self.second_stage_large_page_support(), + ) + .field( + "fault_recording_register_offset", + &self.fault_recording_register_offset(), + ) + .field( + "supported_adjusted_guest_address_widths", + &self.supported_adjusted_guest_address_widths(), + ) + .field("domain_support_number", &self.domain_support_number()) + .field( + "maximum_address_mask_value", + &self.maximum_address_mask_value(), + ) + .field("fault_recording_number", &self.fault_recording_number()) + .field("raw", &self.0) + .finish() + } +} + +bitflags! { + /// Capability flags in IOMMU. + pub struct CapabilityFlags: u64{ + /// Required Write-Buffer Flushing. + const RWBF = 1 << 4; + /// Protected Low-Memory Region + const PLMR = 1 << 5; + /// Protected High-Memory Region + const PHMR = 1 << 6; + /// Caching Mode + const CM = 1 << 7; + /// Zero Length Read. Whether the remapping hardware unit supports zero length DMA + /// read requests to write-only pages. + const ZLR = 1 << 22; + /// Page Selective Invalidation. Whether hardware supports page-selective invalidation + /// for IOTLB. + const PSI = 1 << 39; + /// Write Draining. + const DWD = 1 << 54; + /// Read Draining. + const DRD = 1 << 55; + /// First Stage 1-GByte Page Support. + const FS1GP = 1 << 56; + /// Posted Interrupts Support. + const PI = 1 << 59; + /// First Stage 5-level Paging Support. + const FS5LP = 1 << 60; + /// Enhanced Command Support. + const ECMDS = 1 << 61; + /// Enhanced Set Interrupt Remap Table Pointer Support. + const ESIRTPS = 1 << 62; + /// Enhanced Set Root Table Pointer Support. + const ESRTPS = 1 << 63; + } +} diff --git a/ostd/src/arch/x86/iommu/registers/command.rs b/ostd/src/arch/x86/iommu/registers/command.rs new file mode 100644 index 000000000..140a860ee --- /dev/null +++ b/ostd/src/arch/x86/iommu/registers/command.rs @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MPL-2.0 + +use bitflags::bitflags; + +bitflags! { + /// Global Command to enable functions in IOMMU. All field is write-only. + pub struct GlobalCommand: u32{ + /// Compatibility Format Interrupt, only valid if interrupt-remapping is supported. + /// + /// Interrupt remapping will block compatibility format interrupts if set to 0. + /// Otherwise these interrupts will bypass interrupt remapping. + const CFI = 1 << 23; + /// Set Interrupt Remap Table Pointer, only valid if interrupt-remapping is supported. + /// + /// Software sets this filed to set/update the interrupt remapping table pointer used + /// by hardware. The interrupt remapping table pointer is specified through the Interrupt + /// Remapping Table Address (IRTA_REG) register. + const SIRTP = 1 << 24; + /// Interrupt Remapping Enable, only valid if hardware support interrupt remapping. + /// Set to 1 if enable interrupt-remapping hardware. + /// + /// Hardware reports the status of the interrupt remapping enable operation through the + /// IRES field in the Global Status register. + const IRE = 1 << 25; + /// Queued Invalidation Enable, only valid if hardware support queued invalidations. + /// Set to 1 to enable use of queued validations. + /// + /// Hardware reports the status of queued invalidation enable operation through QIES + /// field in Global Status register. + const QIE = 1 << 26; + /// Write Buffer Flush, only valid for implementations requiring write buffer flushing. + /// + /// Software sets this field to request that hardware flush the Root-Complex + /// internal write buffers. This is done to ensure any updates to the memory resident + /// remapping structures are not held in any internal write posting buffers. + /// + /// Hardware reports the status of the write buffer flushing operation through WBFS + /// field in Global Status register. + const WBF = 1 << 27; + /// Set Root Table Pointer. + /// + /// Software sets this field to set/update the root-table pointer (and translation + /// table mode) used by hardware. The root-table pointer (and translation table + /// mode) is specified through the Root Table Address (RTADDR_REG) register. + const SRTP = 1 << 30; + /// Translation Enable. + /// + /// Software writes to this field to request hardware to enable/disable DMA remapping. + /// + /// 0: Disable DMA remapping; 1: Enable DMA remapping. + /// + /// Hardware reports the status of the translation enable operation through TES field + /// in the Global Status register. + const TE = 1 << 31; + } +} diff --git a/ostd/src/arch/x86/iommu/registers/extended_cap.rs b/ostd/src/arch/x86/iommu/registers/extended_cap.rs new file mode 100644 index 000000000..1f1b5d6b7 --- /dev/null +++ b/ostd/src/arch/x86/iommu/registers/extended_cap.rs @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MPL-2.0 + +use core::fmt::Debug; + +use bitflags::bitflags; + +pub struct ExtendedCapability(u64); + +impl ExtendedCapability { + /// Create ExtendedCapability from `value` + pub const fn new(value: u64) -> Self { + Self(value) + } + + /// Extended capability flags + pub const fn flags(&self) -> ExtendedCapabilityFlags { + ExtendedCapabilityFlags::from_bits_truncate(self.0) + } + + /// IOTLB Register Offset. This field specifies the offset to the IOTLB registers relative + /// to the register base address of this remapping hardware unit. + /// + /// If the register base address is X, and the value reported in this field is Y, the + /// address for the IOTLB registers is calculated as X+(16*Y). + pub const fn iotlb_register_offset(&self) -> u64 { + const IRO_MASK: u64 = 0x3FF << 8; + (self.0 & IRO_MASK) >> 8 + } + + /// Maximum Handle Mask Value, indicates the maximum supported value for the Interrupt + /// Mask (IM) field in the Interrupt Entry Cache Invalidation Descriptorr (iec_inv_dsc). + pub const fn maximum_handle_mask(&self) -> u64 { + const MHMV_MASK: u64 = 0xF << 20; + (self.0 & MHMV_MASK) >> 20 + } + + /// PASID Size Supported, indicates the PASID size supported by the remapping hardware + /// for requests-with-PASID. A value of N in this field indicates hardware supports + /// PASID field of N+1 bits. + /// + /// This field is unused and reported as 0 if Scalable Mode Translation Support (SMTS) + /// field is Clear. + pub const fn pasid_size(&self) -> u64 { + const PSS_MASK: u64 = 0x1F << 35; + (self.0 & PSS_MASK) >> 35 + } +} + +impl Debug for ExtendedCapability { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("ExtendedCapability") + .field("flags", &self.flags()) + .field("maximum_handle_mask", &self.maximum_handle_mask()) + .field("pasid_size", &self.pasid_size()) + .field("iotlb_register_offset", &self.iotlb_register_offset()) + .field("raw", &self.0) + .finish() + } +} + +bitflags! { + /// Extended Capability flags in IOMMU. + /// + /// TODO: Add adetailed description of each flag. + pub struct ExtendedCapabilityFlags: u64{ + /// Page-walk Conherency. + const C = 1 << 0; + /// Queued Invalidation Support. + const QI = 1 << 1; + /// Device-TLB Support. + const DT = 1 << 2; + /// Interrupt Remapping Support + const IR = 1 << 3; + /// Extended Interrupt Mode. + const EIM = 1 << 4; + /// Pass Through Support. + const PT = 1 << 6; + /// Snoop Control. + const SC = 1 << 7; + /// Memory Type Support. + const MTS = 1 << 25; + /// Nested Translation Support. + const NEST = 1 << 26; + /// Page Request Support. + const PRS = 1 << 29; + /// Execute Request Support. + const ERS = 1 << 30; + /// Supervisor Request Support. + const SRS = 1 << 31; + /// No Write Flag Support. + const NWFS = 1 << 33; + /// Extended Accessed Flag Support. + const EAFS = 1 << 34; + /// Process Address Space ID Supported. + const PASID = 1 << 40; + /// Device-TLB Invalidation Throttle. + const DIT = 1 << 41; + /// Page-request Drain Support. + const PDS = 1 << 42; + /// Scalable Mode Translation Support. + const SMTS = 1 << 43; + /// Virtual Command Support. + const VCS = 1 << 44; + /// Second-Stage Accessed/Dirty Support. + const SSADS = 1 << 45; + /// Second-stage Translation Support. + const SSTS = 1 << 46; + /// First-stage Translation Support. + const FSTS = 1 << 47; + /// Scalable-Mode Page-walk Coherency Support. + const SMPWCS = 1 << 48; + /// RID-PASID Support. + const RPS = 1 << 49; + /// Performance Monitoring Support. + const PMS = 1 << 51; + /// Abort DMA Mode Support. + const ADMS = 1 << 52; + /// RID_PRIV Support. + const RPRIVS = 1 << 53; + /// Stop Marker Support. + const SMS = 1 << 58; + } +} diff --git a/ostd/src/arch/x86/iommu/registers/status.rs b/ostd/src/arch/x86/iommu/registers/status.rs new file mode 100644 index 000000000..d74aee87f --- /dev/null +++ b/ostd/src/arch/x86/iommu/registers/status.rs @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MPL-2.0 + +use bitflags::bitflags; + +bitflags! { + /// Global Status of the IOMMU. All fields is read-only. Some description of the fields + /// is related to the fields in `GlobalCommand`. + pub struct GlobalStatus: u32{ + /// Compatibility Format Interrupt Status. The value reported in this field is + /// applicable only when interrupt-remapping is enabled and extended interrupt + /// model (x2APIC) mode is not enables. + /// + /// - 0: Compatibility format interrupts are blocked. + /// - 1: Compatibility format interrupts are processed as pass-through (bypassing + /// interrupt remapping). + const CFIS = 1 << 23; + /// Interrupt Remapping Table Pointer Status. + /// + /// This field is cleared by hardware when software sets the SIRTP field in the Global + /// Command register. This field is Set by hardware when hardware completes the + /// `Set Interrupt Remap Table Pointer` operation using the value provided in the + /// Interrupt Remapping Table Address register. + const IRTPS = 1 << 24; + /// Interrupt Remapping Enable Status. + /// + /// - 0: Interrupt-remapping hardware is not enabled. + /// - 1: Interrupt-remapping hardware is enabled. + const IRES = 1 << 25; + /// Queued Invalidation Enable Status. + /// + /// - 0: queued invalidation is not enabled. + /// - 1: queued invalidation is enabled. + const QIES = 1 << 26; + /// Write Buffer Flush Status. This field is valid only for implementations requiring + /// write buffer flushing. This field indicates the status of the write buffer flush + /// command. + /// + /// - Set by hardware when software sets the WBF field in the Global Command register. + /// - Cleared by hardware when hardware completes the write buffer flushing operation. + const WBFS = 1 << 27; + /// Root Table Pointer Status. + /// + /// This field is cleared by hardware when software sets the SRTP field in the Global + /// Command register. This field is set by hardware when hardware completes the + /// `Set Root Table Pointer`` operation using the value provided in the Root Table + /// Address register. + const RTPS = 1 << 30; + /// Translation Enable Status. + /// + /// - 0: DMA remapping is not enabled. + /// - 1: DMA remapping is enabled. + const TES = 1 << 31; + } +}