Re: [PATCH 13/16] gpu: nova-core: Add support for VBIOS ucode extraction for boot

Joel Fernandes
2025-04-24T19:19:06Z

On Wed, Apr 23, 2025 at 05:02:58PM +0200, Danilo Krummrich wrote:

[..]

> > >> + data.extend_with(len, 0, GFP_KERNEL)?;
> > >> + with_bar!(?bar0, |bar0_ref| {
> > >> + let dst = &mut data[current_len..current_len + len];
> > >> + for (idx, chunk) in dst
> > >> + .chunks_exact_mut(core::mem::size_of::<u32>())
> > >> + .enumerate()
> > >> + {
> > >> + let addr = start + (idx * core::mem::size_of::<u32>());
> > >> + // Convert the u32 to a 4 byte array. We use the .to_ne_bytes()
> > >> + // method out of convenience to convert the 32-bit integer as it
> > >> + // is in memory into a byte array without any endianness
> > >> + // conversion or byte-swapping.
> > >> + chunk.copy_from_slice(&bar0_ref.try_read32(addr)?.to_ne_bytes());
> > >> + }
> > >> + Ok(())
> > >> + })?;
> > >> +
> > >> + Ok(())
> > >> + }
> > ..actually initially was:
> >
> > + with_bar!(self.bar0, |bar0| {
> > + // Get current length
> > + let current_len = self.data.len();
> > +
> > + // Read ROM data bytes push directly to vector
> > + for i in 0..bytes as usize {
> > + // Read byte from the VBIOS ROM and push it to the data vector
> > + let rom_addr = ROM_OFFSET + current_len + i;
> > + let byte = bar0.try_readb(rom_addr)?;
> > + self.data.push(byte, GFP_KERNEL)?;
> >
> > Where this bit could result in a lot of allocation.
> >
> > There was an unsafe() way of not having to do this but we settled with
> > extends_with().
> >
> > Thoughts?
>
> If I understand you correctly, you just want to make sure that subsequent push()
> calls don't re-allocate? If so, you can just use reserve() [1] and keep the
> subsequent push() calls.
>
> [1] https://rust.docs.kernel.org/kernel/alloc/kvec/struct.Vec.html#method.reserve

Ok that does turn out to be cleaner! I replaced it with the following and it works.

Let me know if it looks good now? Here's a preview:

- data.extend_with(len, 0, GFP_KERNEL)?;
+ data.reserve(len, GFP_KERNEL)?;
+
with_bar_res!(bar0, |bar0_ref| {
- let dst = &mut data[current_len..current_len + len];
- for (idx, chunk) in dst
- .chunks_exact_mut(core::mem::size_of::<u32>())
- .enumerate()
- {
- let addr = start + (idx * core::mem::size_of::<u32>());
- // Convert the u32 to a 4 byte array. We use the .to_ne_bytes()
- // method out of convenience to convert the 32-bit integer as it
- // is in memory into a byte array without any endianness
- // conversion or byte-swapping.
- chunk.copy_from_slice(&bar0_ref.try_read32(addr)?.to_ne_bytes());
+ // Read ROM data bytes and push directly to vector
+ for i in 0..len {
+ // Read 32-bit word from the VBIOS ROM
+ let rom_addr = start + i * core::mem::size_of::<u32>();
+ let word = bar0_ref.try_read32(rom_addr)?;
+
+ // Convert the u32 to a 4 byte array and push each byte
+ word.to_ne_bytes().iter().try_for_each(|&b| data.push(b, GFP_KERNEL))?;
}

Thanks.