diff options
| author | Alexandre Courbot <acourbot@nvidia.com> | 2025-10-27 23:12:31 +0900 |
|---|---|---|
| committer | Alexandre Courbot <acourbot@nvidia.com> | 2025-11-08 08:22:45 +0900 |
| commit | 84e2b401bcc551e7c2e1a995f90cce421bce5bfd (patch) | |
| tree | 22c198ec547b70bb4dce9ade00601d5eb0a8eb84 | |
| parent | 5525ac03ca7adec61d39f3fd3a143b5e294bdff7 (diff) | |
gpu: nova-core: replace use of `as` with functions from `num`
Use the newly-introduced `num` module to replace the use of `as`
wherever it is safe to do. This ensures that a given conversion cannot
lose data if its source or destination type ever changes.
Acked-by: Danilo Krummrich <dakr@kernel.org>
[acourbot@nvidia.com: fix merge conflicts after rebase.]
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Message-ID: <20251029-nova-as-v3-5-6a30c7333ad9@nvidia.com>
| -rw-r--r-- | drivers/gpu/nova-core/falcon.rs | 8 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/fb.rs | 7 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/firmware.rs | 12 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/firmware/booter.rs | 37 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/firmware/fwsec.rs | 17 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/firmware/gsp.rs | 6 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/firmware/riscv.rs | 9 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/num.rs | 2 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/regs.rs | 5 | ||||
| -rw-r--r-- | drivers/gpu/nova-core/vbios.rs | 9 |
10 files changed, 70 insertions, 42 deletions
diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs index 8efc910f20af..0116cb918fc8 100644 --- a/drivers/gpu/nova-core/falcon.rs +++ b/drivers/gpu/nova-core/falcon.rs @@ -22,6 +22,10 @@ use crate::{ dma::DmaObject, driver::Bar0, gpu::Chipset, + num::{ + FromSafeCast, + IntoSafeCast, // + }, regs, regs::macros::RegisterBase, // }; @@ -450,7 +454,7 @@ impl<E: FalconEngine + 'static> Falcon<E> { FalconMem::Imem => (load_offsets.src_start, fw.dma_handle()), FalconMem::Dmem => ( 0, - fw.dma_handle_with_offset(load_offsets.src_start as usize)?, + fw.dma_handle_with_offset(load_offsets.src_start.into_safe_cast())?, ), }; if dma_start % DmaAddress::from(DMA_LEN) > 0 { @@ -476,7 +480,7 @@ impl<E: FalconEngine + 'static> Falcon<E> { dev_err!(self.dev, "DMA transfer length overflow"); return Err(EOVERFLOW); } - Some(upper_bound) if upper_bound as usize > fw.size() => { + Some(upper_bound) if usize::from_safe_cast(upper_bound) > fw.size() => { dev_err!(self.dev, "DMA transfer goes beyond range of DMA object"); return Err(EINVAL); } diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs index 989bbfd5bdee..a99223f73367 100644 --- a/drivers/gpu/nova-core/fb.rs +++ b/drivers/gpu/nova-core/fb.rs @@ -17,6 +17,7 @@ use crate::{ dma::DmaObject, driver::Bar0, gpu::Chipset, + num::usize_as_u64, regs, // }; @@ -112,14 +113,14 @@ impl FbLayout { let vga_workspace = { let vga_base = { - const NV_PRAMIN_SIZE: u64 = SZ_1M as u64; + const NV_PRAMIN_SIZE: u64 = usize_as_u64(SZ_1M); let base = fb.end - NV_PRAMIN_SIZE; if hal.supports_display(bar) { match regs::NV_PDISP_VGA_WORKSPACE_BASE::read(bar).vga_workspace_addr() { Some(addr) => { if addr < base { - const VBIOS_WORKSPACE_SIZE: u64 = SZ_128K as u64; + const VBIOS_WORKSPACE_SIZE: u64 = usize_as_u64(SZ_128K); // Point workspace address to end of framebuffer. fb.end - VBIOS_WORKSPACE_SIZE @@ -139,7 +140,7 @@ impl FbLayout { let frts = { const FRTS_DOWN_ALIGN: Alignment = Alignment::new::<SZ_128K>(); - const FRTS_SIZE: u64 = SZ_1M as u64; + const FRTS_SIZE: u64 = usize_as_u64(SZ_1M); let frts_base = vga_workspace.start.align_down(FRTS_DOWN_ALIGN) - FRTS_SIZE; frts_base..frts_base + FRTS_SIZE diff --git a/drivers/gpu/nova-core/firmware.rs b/drivers/gpu/nova-core/firmware.rs index 163b746f03ef..2d2008b33fb4 100644 --- a/drivers/gpu/nova-core/firmware.rs +++ b/drivers/gpu/nova-core/firmware.rs @@ -16,7 +16,11 @@ use kernel::{ use crate::{ dma::DmaObject, falcon::FalconFirmware, - gpu, // + gpu, + num::{ + FromSafeCast, + IntoSafeCast, // + }, }; pub(crate) mod booter; @@ -78,7 +82,7 @@ impl FalconUCodeDescV3 { const HDR_SIZE_SHIFT: u32 = 16; const HDR_SIZE_MASK: u32 = 0xffff0000; - ((self.hdr & HDR_SIZE_MASK) >> HDR_SIZE_SHIFT) as usize + ((self.hdr & HDR_SIZE_MASK) >> HDR_SIZE_SHIFT).into_safe_cast() } } @@ -193,8 +197,8 @@ impl<'a> BinFirmware<'a> { /// Returns the data payload of the firmware, or `None` if the data range is out of bounds of /// the firmware image. fn data(&self) -> Option<&[u8]> { - let fw_start = self.hdr.data_offset as usize; - let fw_size = self.hdr.data_size as usize; + let fw_start = usize::from_safe_cast(self.hdr.data_offset); + let fw_size = usize::from_safe_cast(self.hdr.data_size); self.fw.get(fw_start..fw_start + fw_size) } diff --git a/drivers/gpu/nova-core/firmware/booter.rs b/drivers/gpu/nova-core/firmware/booter.rs index 1e8f6c99fa2e..f107f753214a 100644 --- a/drivers/gpu/nova-core/firmware/booter.rs +++ b/drivers/gpu/nova-core/firmware/booter.rs @@ -34,6 +34,10 @@ use crate::{ Unsigned, // }, gpu::Chipset, + num::{ + FromSafeCast, + IntoSafeCast, // + }, }; /// Local convenience function to return a copy of `S` by reinterpreting the bytes starting at @@ -91,7 +95,7 @@ impl<'a> HsFirmwareV2<'a> { /// /// Fails if the header pointed at by `bin_fw` is not within the bounds of the firmware image. fn new(bin_fw: &BinFirmware<'a>) -> Result<Self> { - frombytes_at::<HsHeaderV2>(bin_fw.fw, bin_fw.hdr.header_offset as usize) + frombytes_at::<HsHeaderV2>(bin_fw.fw, bin_fw.hdr.header_offset.into_safe_cast()) .map(|hdr| Self { hdr, fw: bin_fw.fw }) } @@ -100,7 +104,7 @@ impl<'a> HsFirmwareV2<'a> { /// Fails if the offset of the patch location is outside the bounds of the firmware /// image. fn patch_location(&self) -> Result<u32> { - frombytes_at::<u32>(self.fw, self.hdr.patch_loc_offset as usize) + frombytes_at::<u32>(self.fw, self.hdr.patch_loc_offset.into_safe_cast()) } /// Returns an iterator to the signatures of the firmware. The iterator can be empty if the @@ -108,19 +112,23 @@ impl<'a> HsFirmwareV2<'a> { /// /// Fails if the pointed signatures are outside the bounds of the firmware image. fn signatures_iter(&'a self) -> Result<impl Iterator<Item = BooterSignature<'a>>> { - let num_sig = frombytes_at::<u32>(self.fw, self.hdr.num_sig_offset as usize)?; + let num_sig = frombytes_at::<u32>(self.fw, self.hdr.num_sig_offset.into_safe_cast())?; let iter = match self.hdr.sig_prod_size.checked_div(num_sig) { // If there are no signatures, return an iterator that will yield zero elements. None => (&[] as &[u8]).chunks_exact(1), Some(sig_size) => { - let patch_sig = frombytes_at::<u32>(self.fw, self.hdr.patch_sig_offset as usize)?; - let signatures_start = (self.hdr.sig_prod_offset + patch_sig) as usize; + let patch_sig = + frombytes_at::<u32>(self.fw, self.hdr.patch_sig_offset.into_safe_cast())?; + let signatures_start = usize::from_safe_cast(self.hdr.sig_prod_offset + patch_sig); self.fw // Get signatures range. - .get(signatures_start..signatures_start + self.hdr.sig_prod_size as usize) + .get( + signatures_start + ..signatures_start + usize::from_safe_cast(self.hdr.sig_prod_size), + ) .ok_or(EINVAL)? - .chunks_exact(sig_size as usize) + .chunks_exact(sig_size.into_safe_cast()) } }; @@ -149,9 +157,9 @@ impl HsSignatureParams { /// Fails if the meta data parameter of `hs_fw` is outside the bounds of the firmware image, or /// if its size doesn't match that of [`HsSignatureParams`]. fn new(hs_fw: &HsFirmwareV2<'_>) -> Result<Self> { - let start = hs_fw.hdr.meta_data_offset as usize; + let start = usize::from_safe_cast(hs_fw.hdr.meta_data_offset); let end = start - .checked_add(hs_fw.hdr.meta_data_size as usize) + .checked_add(hs_fw.hdr.meta_data_size.into_safe_cast()) .ok_or(EINVAL)?; hs_fw @@ -186,7 +194,7 @@ impl HsLoadHeaderV2 { /// /// Fails if the header pointed at by `hs_fw` is not within the bounds of the firmware image. fn new(hs_fw: &HsFirmwareV2<'_>) -> Result<Self> { - frombytes_at::<Self>(hs_fw.fw, hs_fw.hdr.header_offset as usize) + frombytes_at::<Self>(hs_fw.fw, hs_fw.hdr.header_offset.into_safe_cast()) } } @@ -215,12 +223,13 @@ impl HsLoadHeaderV2App { } else { frombytes_at::<Self>( hs_fw.fw, - (hs_fw.hdr.header_offset as usize) + usize::from_safe_cast(hs_fw.hdr.header_offset) // Skip the load header... .checked_add(size_of::<HsLoadHeaderV2>()) // ... and jump to app header `idx`. .and_then(|offset| { - offset.checked_add((idx as usize).checked_mul(size_of::<Self>())?) + offset + .checked_add(usize::from_safe_cast(idx).checked_mul(size_of::<Self>())?) }) .ok_or(EINVAL)?, ) @@ -335,12 +344,12 @@ impl BooterFirmware { dev_err!(dev, "invalid fuse version for Booter firmware\n"); return Err(EINVAL); }; - signatures.nth(idx as usize) + signatures.nth(idx.into_safe_cast()) } } .ok_or(EINVAL)?; - ucode.patch_signature(&signature, patch_loc as usize)? + ucode.patch_signature(&signature, patch_loc.into_safe_cast())? } }; diff --git a/drivers/gpu/nova-core/firmware/fwsec.rs b/drivers/gpu/nova-core/firmware/fwsec.rs index cb794e406395..b28e34d279f4 100644 --- a/drivers/gpu/nova-core/firmware/fwsec.rs +++ b/drivers/gpu/nova-core/firmware/fwsec.rs @@ -46,6 +46,10 @@ use crate::{ Signed, Unsigned, // }, + num::{ + FromSafeCast, + IntoSafeCast, // + }, vbios::Vbios, }; @@ -267,7 +271,7 @@ impl FirmwareDmaObject<FwsecFirmware, Unsigned> { let ucode = bios.fwsec_image().ucode(desc)?; let mut dma_object = DmaObject::from_data(dev, ucode)?; - let hdr_offset = (desc.imem_load_size + desc.interface_offset) as usize; + let hdr_offset = usize::from_safe_cast(desc.imem_load_size + desc.interface_offset); // SAFETY: we have exclusive access to `dma_object`. let hdr: &FalconAppifHdrV1 = unsafe { transmute(&dma_object, hdr_offset) }?; @@ -292,7 +296,10 @@ impl FirmwareDmaObject<FwsecFirmware, Unsigned> { // SAFETY: we have exclusive access to `dma_object`. let dmem_mapper: &mut FalconAppifDmemmapperV3 = unsafe { - transmute_mut(&mut dma_object, (desc.imem_load_size + dmem_base) as usize) + transmute_mut( + &mut dma_object, + (desc.imem_load_size + dmem_base).into_safe_cast(), + ) }?; dmem_mapper.init_cmd = match cmd { @@ -305,7 +312,7 @@ impl FirmwareDmaObject<FwsecFirmware, Unsigned> { let frts_cmd: &mut FrtsCmd = unsafe { transmute_mut( &mut dma_object, - (desc.imem_load_size + cmd_in_buffer_offset) as usize, + (desc.imem_load_size + cmd_in_buffer_offset).into_safe_cast(), ) }?; @@ -353,7 +360,7 @@ impl FwsecFirmware { // Patch signature if needed. let desc = bios.fwsec_image().header()?; let ucode_signed = if desc.signature_count != 0 { - let sig_base_img = (desc.imem_load_size + desc.pkc_data_offset) as usize; + let sig_base_img = usize::from_safe_cast(desc.imem_load_size + desc.pkc_data_offset); let desc_sig_versions = u32::from(desc.signature_versions); let reg_fuse_version = falcon.signature_reg_fuse_version(bar, desc.engine_id_mask, desc.ucode_id)?; @@ -384,7 +391,7 @@ impl FwsecFirmware { // Mask of the bits of `desc_sig_versions` to preserve. let reg_fuse_version_mask = reg_fuse_version_bit.wrapping_sub(1); - (desc_sig_versions & reg_fuse_version_mask).count_ones() as usize + usize::from_safe_cast((desc_sig_versions & reg_fuse_version_mask).count_ones()) }; dev_dbg!(dev, "patching signature with index {}\n", signature_idx); diff --git a/drivers/gpu/nova-core/firmware/gsp.rs b/drivers/gpu/nova-core/firmware/gsp.rs index 939e036896bf..72766feae36e 100644 --- a/drivers/gpu/nova-core/firmware/gsp.rs +++ b/drivers/gpu/nova-core/firmware/gsp.rs @@ -24,6 +24,7 @@ use crate::{ Chipset, // }, gsp::GSP_PAGE_SIZE, + num::FromSafeCast, }; /// Ad-hoc and temporary module to extract sections from ELF images. @@ -245,10 +246,11 @@ impl GspFirmware { fn map_into_lvl(sg_table: &SGTable<Owned<VVec<u8>>>, mut dst: VVec<u8>) -> Result<VVec<u8>> { for sg_entry in sg_table.iter() { // Number of pages we need to map. - let num_pages = (sg_entry.dma_len() as usize).div_ceil(GSP_PAGE_SIZE); + let num_pages = usize::from_safe_cast(sg_entry.dma_len()).div_ceil(GSP_PAGE_SIZE); for i in 0..num_pages { - let entry = sg_entry.dma_address() + (i as u64 * GSP_PAGE_SIZE as u64); + let entry = sg_entry.dma_address() + + (u64::from_safe_cast(i) * u64::from_safe_cast(GSP_PAGE_SIZE)); dst.extend_from_slice(&entry.to_le_bytes(), GFP_KERNEL)?; } } diff --git a/drivers/gpu/nova-core/firmware/riscv.rs b/drivers/gpu/nova-core/firmware/riscv.rs index 196dedb96aeb..270b2c7dc219 100644 --- a/drivers/gpu/nova-core/firmware/riscv.rs +++ b/drivers/gpu/nova-core/firmware/riscv.rs @@ -14,7 +14,8 @@ use kernel::{ use crate::{ dma::DmaObject, - firmware::BinFirmware, // + firmware::BinFirmware, + num::FromSafeCast, // }; /// Descriptor for microcode running on a RISC-V core. @@ -45,7 +46,7 @@ impl RmRiscvUCodeDesc { /// /// Fails if the header pointed at by `bin_fw` is not within the bounds of the firmware image. fn new(bin_fw: &BinFirmware<'_>) -> Result<Self> { - let offset = bin_fw.hdr.header_offset as usize; + let offset = usize::from_safe_cast(bin_fw.hdr.header_offset); bin_fw .fw @@ -78,8 +79,8 @@ impl RiscvFirmware { let riscv_desc = RmRiscvUCodeDesc::new(&bin_fw)?; let ucode = { - let start = bin_fw.hdr.data_offset as usize; - let len = bin_fw.hdr.data_size as usize; + let start = usize::from_safe_cast(bin_fw.hdr.data_offset); + let len = usize::from_safe_cast(bin_fw.hdr.data_size); DmaObject::from_data(dev, fw.data().get(start..start + len).ok_or(EINVAL)?)? }; diff --git a/drivers/gpu/nova-core/num.rs b/drivers/gpu/nova-core/num.rs index 457a1303640f..92a91b9e30de 100644 --- a/drivers/gpu/nova-core/num.rs +++ b/drivers/gpu/nova-core/num.rs @@ -106,7 +106,6 @@ impl_safe_as!(usize as { u32 }); /// /// assert_eq!(usize::from_safe_cast(0xf00u32), 0xf00u32 as usize); /// ``` -#[expect(unused)] pub(crate) trait FromSafeCast<T> { /// Create a `Self` from `value`. This operation is guaranteed to be lossless. fn from_safe_cast(value: T) -> Self; @@ -150,7 +149,6 @@ impl FromSafeCast<u64> for usize { /// /// assert_eq!(0xf00u32.into_safe_cast(), 0xf00u32 as usize); /// ``` -#[expect(unused)] pub(crate) trait IntoSafeCast<T> { /// Convert `self` into a `T`. This operation is guaranteed to be lossless. fn into_safe_cast(self) -> T; diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs index 7cd2e8a4d4c6..934003cab8a8 100644 --- a/drivers/gpu/nova-core/regs.rs +++ b/drivers/gpu/nova-core/regs.rs @@ -26,6 +26,7 @@ use crate::{ Architecture, Chipset, // }, + num::FromSafeCast, }; // PMC @@ -89,7 +90,7 @@ impl NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE { /// Returns the usable framebuffer size, in bytes. pub(crate) fn usable_fb_size(self) -> u64 { let size = (u64::from(self.lower_mag()) << u64::from(self.lower_scale())) - * kernel::sizes::SZ_1M as u64; + * u64::from_safe_cast(kernel::sizes::SZ_1M); if self.ecc_mode_enabled() { // Remove the amount of memory reserved for ECC (one per 16 units). @@ -172,7 +173,7 @@ register!( impl NV_USABLE_FB_SIZE_IN_MB { /// Returns the usable framebuffer size, in bytes. pub(crate) fn usable_fb_size(self) -> u64 { - u64::from(self.value()) * kernel::sizes::SZ_1M as u64 + u64::from(self.value()) * u64::from_safe_cast(kernel::sizes::SZ_1M) } } diff --git a/drivers/gpu/nova-core/vbios.rs b/drivers/gpu/nova-core/vbios.rs index 9c5b93adeb96..abf423560ff4 100644 --- a/drivers/gpu/nova-core/vbios.rs +++ b/drivers/gpu/nova-core/vbios.rs @@ -21,6 +21,7 @@ use crate::{ fwsec::Bcrt30Rsa3kSignature, FalconUCodeDescV3, // }, + num::FromSafeCast, }; /// The offset of the VBIOS ROM in the BAR0 space. @@ -795,7 +796,7 @@ impl PciAtBiosImage { let data_ptr = u32::from_le_bytes(bytes); - if (data_ptr as usize) < self.base.data.len() { + if (usize::from_safe_cast(data_ptr)) < self.base.data.len() { dev_err!(self.base.dev, "Falcon data pointer out of bounds\n"); return Err(EINVAL); } @@ -922,7 +923,7 @@ impl FwSecBiosBuilder { pci_at_image: &PciAtBiosImage, first_fwsec: &FwSecBiosBuilder, ) -> Result { - let mut offset = pci_at_image.falcon_data_ptr()? as usize; + let mut offset = usize::from_safe_cast(pci_at_image.falcon_data_ptr()?); let mut pmu_in_first_fwsec = false; // The falcon data pointer assumes that the PciAt and FWSEC images @@ -963,7 +964,7 @@ impl FwSecBiosBuilder { .find_entry_by_type(FALCON_UCODE_ENTRY_APPID_FWSEC_PROD) { Ok(entry) => { - let mut ucode_offset = entry.data as usize; + let mut ucode_offset = usize::from_safe_cast(entry.data); ucode_offset -= pci_at_image.base.data.len(); if ucode_offset < first_fwsec.base.data.len() { dev_err!(self.base.dev, "Falcon Ucode offset not in second Fwsec.\n"); @@ -1049,7 +1050,7 @@ impl FwSecBiosImage { // The ucode data follows the descriptor. let ucode_data_offset = falcon_ucode_offset + desc.size(); - let size = (desc.imem_load_size + desc.dmem_load_size) as usize; + let size = usize::from_safe_cast(desc.imem_load_size + desc.dmem_load_size); // Get the data slice, checking bounds in a single operation. self.base |