From 51cd7a01c66b31c40ec1e067673e695d6cc2b690 Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Sat, 15 Jun 2024 00:58:17 +0100 Subject: [PATCH 1/3] Support 64-bit addressing in MSI capabilities --- src/capability/msi.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/capability/msi.rs b/src/capability/msi.rs index 6ec65a1..5d6dd87 100644 --- a/src/capability/msi.rs +++ b/src/capability/msi.rs @@ -113,22 +113,27 @@ impl MsiCapability { MultipleMessageSupport::try_from(reg.get_bits(4..7) as u8).unwrap_or(MultipleMessageSupport::Int1) } - /// Set where the interrupts will be sent to + /// Set the memory address that will be written to when the interrupt fires. /// /// # Arguments - /// * `address` - Target Local APIC address (if not changed, can be calculated with `0xFEE00000 | (processor << 12)`) + /// * `address` - Target Local APIC address (if not changed, can be calculated with `0xfee00000 | (processor << 12)`) /// * `vector` - Which interrupt vector should be triggered on LAPIC /// * `trigger_mode` - When interrupt should be triggered /// * `access` - PCI Configuration Space accessor pub fn set_message_info( &self, - address: u32, + address: u64, vector: u8, trigger_mode: TriggerMode, access: impl ConfigRegionAccess, ) { - unsafe { access.write(self.address.address, self.address.offset + 0x4, address) } - let data_offset = if self.is_64bit { 0xC } else { 0x8 }; + unsafe { + access.write(self.address.address, self.address.offset + 0x04, address.get_bits(0..32) as u32); + if self.is_64bit { + access.write(self.address.address, self.address.offset + 0x08, address.get_bits(32..64) as u32); + } + } + let data_offset = if self.is_64bit { 0x0c } else { 0x08 }; let mut data = unsafe { access.read(self.address.address, self.address.offset + data_offset) }; data.set_bits(0..8, vector as u32); data.set_bits(14..16, trigger_mode as u32); From 0030b7b4747acca4a20062f3fc5aa01030d94bc8 Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Sat, 15 Jun 2024 00:58:38 +0100 Subject: [PATCH 2/3] Make naming in `MsiCapability` more uniform with rest of library --- src/capability/msi.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/capability/msi.rs b/src/capability/msi.rs index 5d6dd87..b3c7575 100644 --- a/src/capability/msi.rs +++ b/src/capability/msi.rs @@ -78,7 +78,7 @@ impl MsiCapability { /// How many interrupts this device has? #[inline] - pub fn get_multiple_message_capable(&self) -> MultipleMessageSupport { + pub fn multiple_message_capable(&self) -> MultipleMessageSupport { self.multiple_message_capable } @@ -108,7 +108,7 @@ impl MsiCapability { } /// Return how many interrupts the device is using - pub fn get_multiple_message_enable(&self, access: impl ConfigRegionAccess) -> MultipleMessageSupport { + pub fn multiple_message_enable(&self, access: impl ConfigRegionAccess) -> MultipleMessageSupport { let reg = unsafe { access.read(self.address.address, self.address.offset) }; MultipleMessageSupport::try_from(reg.get_bits(4..7) as u8).unwrap_or(MultipleMessageSupport::Int1) } @@ -145,7 +145,7 @@ impl MsiCapability { /// # Note /// Only supported on when device supports 64-bit addressing and per-vector masking. Otherwise /// returns `0` - pub fn get_message_mask(&self, access: impl ConfigRegionAccess) -> u32 { + pub fn message_mask(&self, access: impl ConfigRegionAccess) -> u32 { if self.is_64bit && self.per_vector_masking { unsafe { access.read(self.address.address, self.address.offset + 0x10) } } else { @@ -158,7 +158,7 @@ impl MsiCapability { /// # Note /// Only supported on when device supports 64-bit addressing and per-vector masking. Otherwise /// will do nothing - pub fn set_message_mask(&self, access: impl ConfigRegionAccess, mask: u32) { + pub fn set_message_mask(&self, mask: u32, access: impl ConfigRegionAccess) { if self.is_64bit && self.per_vector_masking { unsafe { access.write(self.address.address, self.address.offset + 0x10, mask) } } @@ -168,7 +168,7 @@ impl MsiCapability { /// /// # Note /// Only supported on when device supports 64-bit addressing. Otherwise will return `0` - pub fn get_pending(&self, access: impl ConfigRegionAccess) -> u32 { + pub fn is_pending(&self, access: impl ConfigRegionAccess) -> u32 { if self.is_64bit { unsafe { access.read(self.address.address, self.address.offset + 0x14) } } else { From ce0ffeb3773fa73f05ee107e21949faaa7beda1c Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Sat, 15 Jun 2024 01:26:33 +0100 Subject: [PATCH 3/3] Separate out message info helpers for MSI capabilities --- src/capability/msi.rs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/capability/msi.rs b/src/capability/msi.rs index b3c7575..20ec305 100644 --- a/src/capability/msi.rs +++ b/src/capability/msi.rs @@ -113,31 +113,40 @@ impl MsiCapability { MultipleMessageSupport::try_from(reg.get_bits(4..7) as u8).unwrap_or(MultipleMessageSupport::Int1) } - /// Set the memory address that will be written to when the interrupt fires. + /// Set the memory address that will be written to when the interrupt fires, and the data that + /// will be written to it. + pub fn set_message_info(&self, address: u64, data: u32, access: impl ConfigRegionAccess) { + unsafe { + access.write(self.address.address, self.address.offset + 0x04, address.get_bits(0..32) as u32); + if self.is_64bit { + access.write(self.address.address, self.address.offset + 0x08, address.get_bits(32..64) as u32); + } + } + let data_offset = if self.is_64bit { 0x0c } else { 0x08 }; + unsafe { + access.write(self.address.address, self.address.offset + data_offset, data); + } + } + + /// Set the memory address that will be written to when the interrupt fires, and the data that + /// will be written to it, specialised for the message format the LAPIC expects. /// /// # Arguments /// * `address` - Target Local APIC address (if not changed, can be calculated with `0xfee00000 | (processor << 12)`) /// * `vector` - Which interrupt vector should be triggered on LAPIC /// * `trigger_mode` - When interrupt should be triggered /// * `access` - PCI Configuration Space accessor - pub fn set_message_info( + pub fn set_message_info_lapic( &self, address: u64, vector: u8, trigger_mode: TriggerMode, access: impl ConfigRegionAccess, ) { - unsafe { - access.write(self.address.address, self.address.offset + 0x04, address.get_bits(0..32) as u32); - if self.is_64bit { - access.write(self.address.address, self.address.offset + 0x08, address.get_bits(32..64) as u32); - } - } - let data_offset = if self.is_64bit { 0x0c } else { 0x08 }; - let mut data = unsafe { access.read(self.address.address, self.address.offset + data_offset) }; + let mut data = 0; data.set_bits(0..8, vector as u32); data.set_bits(14..16, trigger_mode as u32); - unsafe { access.write(self.address.address, self.address.offset + data_offset, data) } + self.set_message_info(address, data, access); } /// Get interrupt mask