Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: io: factor out MMIO read/write macros

Refactor the existing MMIO accessors to use common call macros
instead of inlining the bindings calls in each `define_{read,write}!`
expansion.

This factoring separates the common offset/bounds checks from the
low-level call pattern, making it easier to add additional I/O accessor
families.

No functional change intended.

Cc: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Link: https://patch.msgid.link/20260121202212.4438-4-zhiw@nvidia.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

authored by

Zhi Wang and committed by
Danilo Krummrich
5981d03c 121d87b2

+102 -45
+102 -45
rust/kernel/io.rs
··· 137 137 #[repr(transparent)] 138 138 pub struct Mmio<const SIZE: usize = 0>(MmioRaw<SIZE>); 139 139 140 + /// Internal helper macros used to invoke C MMIO read functions. 141 + /// 142 + /// This macro is intended to be used by higher-level MMIO access macros (define_read) and provides 143 + /// a unified expansion for infallible vs. fallible read semantics. It emits a direct call into the 144 + /// corresponding C helper and performs the required cast to the Rust return type. 145 + /// 146 + /// # Parameters 147 + /// 148 + /// * `$c_fn` – The C function performing the MMIO read. 149 + /// * `$self` – The I/O backend object. 150 + /// * `$ty` – The type of the value to be read. 151 + /// * `$addr` – The MMIO address to read. 152 + /// 153 + /// This macro does not perform any validation; all invariants must be upheld by the higher-level 154 + /// abstraction invoking it. 155 + macro_rules! call_mmio_read { 156 + (infallible, $c_fn:ident, $self:ident, $type:ty, $addr:expr) => { 157 + // SAFETY: By the type invariant `addr` is a valid address for MMIO operations. 158 + unsafe { bindings::$c_fn($addr as *const c_void) as $type } 159 + }; 160 + 161 + (fallible, $c_fn:ident, $self:ident, $type:ty, $addr:expr) => {{ 162 + // SAFETY: By the type invariant `addr` is a valid address for MMIO operations. 163 + Ok(unsafe { bindings::$c_fn($addr as *const c_void) as $type }) 164 + }}; 165 + } 166 + 167 + /// Internal helper macros used to invoke C MMIO write functions. 168 + /// 169 + /// This macro is intended to be used by higher-level MMIO access macros (define_write) and provides 170 + /// a unified expansion for infallible vs. fallible write semantics. It emits a direct call into the 171 + /// corresponding C helper and performs the required cast to the Rust return type. 172 + /// 173 + /// # Parameters 174 + /// 175 + /// * `$c_fn` – The C function performing the MMIO write. 176 + /// * `$self` – The I/O backend object. 177 + /// * `$ty` – The type of the written value. 178 + /// * `$addr` – The MMIO address to write. 179 + /// * `$value` – The value to write. 180 + /// 181 + /// This macro does not perform any validation; all invariants must be upheld by the higher-level 182 + /// abstraction invoking it. 183 + macro_rules! call_mmio_write { 184 + (infallible, $c_fn:ident, $self:ident, $ty:ty, $addr:expr, $value:expr) => { 185 + // SAFETY: By the type invariant `addr` is a valid address for MMIO operations. 186 + unsafe { bindings::$c_fn($value, $addr as *mut c_void) } 187 + }; 188 + 189 + (fallible, $c_fn:ident, $self:ident, $ty:ty, $addr:expr, $value:expr) => {{ 190 + // SAFETY: By the type invariant `addr` is a valid address for MMIO operations. 191 + unsafe { bindings::$c_fn($value, $addr as *mut c_void) }; 192 + Ok(()) 193 + }}; 194 + } 195 + 140 196 macro_rules! define_read { 141 - (infallible, $(#[$attr:meta])* $vis:vis $name:ident, $c_fn:ident -> $type_name:ty) => { 197 + (infallible, $(#[$attr:meta])* $vis:vis $name:ident, $call_macro:ident($c_fn:ident) -> 198 + $type_name:ty) => { 142 199 /// Read IO data from a given offset known at compile time. 143 200 /// 144 201 /// Bound checks are performed on compile time, hence if the offset is not known at compile ··· 205 148 $vis fn $name(&self, offset: usize) -> $type_name { 206 149 let addr = self.io_addr_assert::<$type_name>(offset); 207 150 208 - // SAFETY: By the type invariant `addr` is a valid address for MMIO operations. 209 - unsafe { bindings::$c_fn(addr as *const c_void) } 151 + // SAFETY: By the type invariant `addr` is a valid address for IO operations. 152 + $call_macro!(infallible, $c_fn, self, $type_name, addr) 210 153 } 211 154 }; 212 155 213 - (fallible, $(#[$attr:meta])* $vis:vis $try_name:ident, $c_fn:ident -> $type_name:ty) => { 156 + (fallible, $(#[$attr:meta])* $vis:vis $try_name:ident, $call_macro:ident($c_fn:ident) -> 157 + $type_name:ty) => { 214 158 /// Read IO data from a given offset. 215 159 /// 216 160 /// Bound checks are performed on runtime, it fails if the offset (plus the type size) is ··· 220 162 $vis fn $try_name(&self, offset: usize) -> Result<$type_name> { 221 163 let addr = self.io_addr::<$type_name>(offset)?; 222 164 223 - // SAFETY: By the type invariant `addr` is a valid address for MMIO operations. 224 - Ok(unsafe { bindings::$c_fn(addr as *const c_void) }) 165 + // SAFETY: By the type invariant `addr` is a valid address for IO operations. 166 + $call_macro!(fallible, $c_fn, self, $type_name, addr) 225 167 } 226 168 }; 227 169 } ··· 229 171 pub(crate) use define_read; 230 172 231 173 macro_rules! define_write { 232 - (infallible, $(#[$attr:meta])* $vis:vis $name:ident, $c_fn:ident <- $type_name:ty) => { 174 + (infallible, $(#[$attr:meta])* $vis:vis $name:ident, $call_macro:ident($c_fn:ident) <- 175 + $type_name:ty) => { 233 176 /// Write IO data from a given offset known at compile time. 234 177 /// 235 178 /// Bound checks are performed on compile time, hence if the offset is not known at compile ··· 240 181 $vis fn $name(&self, value: $type_name, offset: usize) { 241 182 let addr = self.io_addr_assert::<$type_name>(offset); 242 183 243 - // SAFETY: By the type invariant `addr` is a valid address for MMIO operations. 244 - unsafe { bindings::$c_fn(value, addr as *mut c_void) } 184 + $call_macro!(infallible, $c_fn, self, $type_name, addr, value); 245 185 } 246 186 }; 247 187 248 - (fallible, $(#[$attr:meta])* $vis:vis $try_name:ident, $c_fn:ident <- $type_name:ty) => { 188 + (fallible, $(#[$attr:meta])* $vis:vis $try_name:ident, $call_macro:ident($c_fn:ident) <- 189 + $type_name:ty) => { 249 190 /// Write IO data from a given offset. 250 191 /// 251 192 /// Bound checks are performed on runtime, it fails if the offset (plus the type size) is ··· 254 195 $vis fn $try_name(&self, value: $type_name, offset: usize) -> Result { 255 196 let addr = self.io_addr::<$type_name>(offset)?; 256 197 257 - // SAFETY: By the type invariant `addr` is a valid address for MMIO operations. 258 - unsafe { bindings::$c_fn(value, addr as *mut c_void) }; 259 - Ok(()) 198 + $call_macro!(fallible, $c_fn, self, $type_name, addr, value) 260 199 } 261 200 }; 262 201 } ··· 510 453 self.0.maxsize() 511 454 } 512 455 513 - define_read!(fallible, try_read8, readb -> u8); 514 - define_read!(fallible, try_read16, readw -> u16); 515 - define_read!(fallible, try_read32, readl -> u32); 456 + define_read!(fallible, try_read8, call_mmio_read(readb) -> u8); 457 + define_read!(fallible, try_read16, call_mmio_read(readw) -> u16); 458 + define_read!(fallible, try_read32, call_mmio_read(readl) -> u32); 516 459 define_read!( 517 460 fallible, 518 461 #[cfg(CONFIG_64BIT)] 519 462 try_read64, 520 - readq -> u64 463 + call_mmio_read(readq) -> u64 521 464 ); 522 465 523 - define_write!(fallible, try_write8, writeb <- u8); 524 - define_write!(fallible, try_write16, writew <- u16); 525 - define_write!(fallible, try_write32, writel <- u32); 466 + define_write!(fallible, try_write8, call_mmio_write(writeb) <- u8); 467 + define_write!(fallible, try_write16, call_mmio_write(writew) <- u16); 468 + define_write!(fallible, try_write32, call_mmio_write(writel) <- u32); 526 469 define_write!( 527 470 fallible, 528 471 #[cfg(CONFIG_64BIT)] 529 472 try_write64, 530 - writeq <- u64 473 + call_mmio_write(writeq) <- u64 531 474 ); 532 475 533 - define_read!(infallible, read8, readb -> u8); 534 - define_read!(infallible, read16, readw -> u16); 535 - define_read!(infallible, read32, readl -> u32); 476 + define_read!(infallible, read8, call_mmio_read(readb) -> u8); 477 + define_read!(infallible, read16, call_mmio_read(readw) -> u16); 478 + define_read!(infallible, read32, call_mmio_read(readl) -> u32); 536 479 define_read!( 537 480 infallible, 538 481 #[cfg(CONFIG_64BIT)] 539 482 read64, 540 - readq -> u64 483 + call_mmio_read(readq) -> u64 541 484 ); 542 485 543 - define_write!(infallible, write8, writeb <- u8); 544 - define_write!(infallible, write16, writew <- u16); 545 - define_write!(infallible, write32, writel <- u32); 486 + define_write!(infallible, write8, call_mmio_write(writeb) <- u8); 487 + define_write!(infallible, write16, call_mmio_write(writew) <- u16); 488 + define_write!(infallible, write32, call_mmio_write(writel) <- u32); 546 489 define_write!( 547 490 infallible, 548 491 #[cfg(CONFIG_64BIT)] 549 492 write64, 550 - writeq <- u64 493 + call_mmio_write(writeq) <- u64 551 494 ); 552 495 } 553 496 ··· 565 508 unsafe { &*core::ptr::from_ref(raw).cast() } 566 509 } 567 510 568 - define_read!(infallible, pub read8_relaxed, readb_relaxed -> u8); 569 - define_read!(infallible, pub read16_relaxed, readw_relaxed -> u16); 570 - define_read!(infallible, pub read32_relaxed, readl_relaxed -> u32); 511 + define_read!(infallible, pub read8_relaxed, call_mmio_read(readb_relaxed) -> u8); 512 + define_read!(infallible, pub read16_relaxed, call_mmio_read(readw_relaxed) -> u16); 513 + define_read!(infallible, pub read32_relaxed, call_mmio_read(readl_relaxed) -> u32); 571 514 define_read!( 572 515 infallible, 573 516 #[cfg(CONFIG_64BIT)] 574 517 pub read64_relaxed, 575 - readq_relaxed -> u64 518 + call_mmio_read(readq_relaxed) -> u64 576 519 ); 577 520 578 - define_read!(fallible, pub try_read8_relaxed, readb_relaxed -> u8); 579 - define_read!(fallible, pub try_read16_relaxed, readw_relaxed -> u16); 580 - define_read!(fallible, pub try_read32_relaxed, readl_relaxed -> u32); 521 + define_read!(fallible, pub try_read8_relaxed, call_mmio_read(readb_relaxed) -> u8); 522 + define_read!(fallible, pub try_read16_relaxed, call_mmio_read(readw_relaxed) -> u16); 523 + define_read!(fallible, pub try_read32_relaxed, call_mmio_read(readl_relaxed) -> u32); 581 524 define_read!( 582 525 fallible, 583 526 #[cfg(CONFIG_64BIT)] 584 527 pub try_read64_relaxed, 585 - readq_relaxed -> u64 528 + call_mmio_read(readq_relaxed) -> u64 586 529 ); 587 530 588 - define_write!(infallible, pub write8_relaxed, writeb_relaxed <- u8); 589 - define_write!(infallible, pub write16_relaxed, writew_relaxed <- u16); 590 - define_write!(infallible, pub write32_relaxed, writel_relaxed <- u32); 531 + define_write!(infallible, pub write8_relaxed, call_mmio_write(writeb_relaxed) <- u8); 532 + define_write!(infallible, pub write16_relaxed, call_mmio_write(writew_relaxed) <- u16); 533 + define_write!(infallible, pub write32_relaxed, call_mmio_write(writel_relaxed) <- u32); 591 534 define_write!( 592 535 infallible, 593 536 #[cfg(CONFIG_64BIT)] 594 537 pub write64_relaxed, 595 - writeq_relaxed <- u64 538 + call_mmio_write(writeq_relaxed) <- u64 596 539 ); 597 540 598 - define_write!(fallible, pub try_write8_relaxed, writeb_relaxed <- u8); 599 - define_write!(fallible, pub try_write16_relaxed, writew_relaxed <- u16); 600 - define_write!(fallible, pub try_write32_relaxed, writel_relaxed <- u32); 541 + define_write!(fallible, pub try_write8_relaxed, call_mmio_write(writeb_relaxed) <- u8); 542 + define_write!(fallible, pub try_write16_relaxed, call_mmio_write(writew_relaxed) <- u16); 543 + define_write!(fallible, pub try_write32_relaxed, call_mmio_write(writel_relaxed) <- u32); 601 544 define_write!( 602 545 fallible, 603 546 #[cfg(CONFIG_64BIT)] 604 547 pub try_write64_relaxed, 605 - writeq_relaxed <- u64 548 + call_mmio_write(writeq_relaxed) <- u64 606 549 ); 607 550 }