Thank you for your contribution! Sashiko AI review found 2 potential issue(s) 
to consider:
- [High] The NVKV wire format encoder improperly depends on the host's native 
endianness, generating a different sequence of 64-bit values on big-endian 
versus little-endian architectures. This corrupts the GPU command stream on 
big-endian systems.
- [Low] Missing `#[inline(always)]` on the `From<Opcode>` implementation that 
delegates to an assertion requiring constant evaluation.
--

commit dbc5c487fe7e32cc1bab7a9eae25bab7cbbe966a
Author: Eliot Courtney <[email protected]>

gpu: nova-core: add NVKV encoder

This commit introduces an NVKV encoder for GMCAPI wire formats, converting
sequences of key-value operations into a stream of 64-bit words. The driver
encodes primitives like 32-bit/64-bit values and arrays using specific opcodes.
Tests are included to verify the binary layout of the encoded output.

> diff --git a/drivers/gpu/nova-core/gsp/nvkv.rs 
> b/drivers/gpu/nova-core/gsp/nvkv.rs
> new file mode 100644
> index 0000000000000..a8e16687a134b
> --- /dev/null
> +++ b/drivers/gpu/nova-core/gsp/nvkv.rs
[ ... ]
> +    fn extend_with_padding<T: IntoBytes + Immutable + ?Sized>(&mut self, 
> data: &T) -> Result {
> +        let bytes = data.as_bytes();
> +        let padded = bytes.len().next_multiple_of(size_of::<u64>());
> +        // Reserve so that a failed allocation can't leave the invariant 
> violated.
> +        self.0.reserve(padded, GFP_KERNEL)?;
> +        self.0.extend_from_slice(bytes, GFP_KERNEL)?;

[Severity: High]
Does copying the memory representation directly using data.as_bytes() rely
on the host's native endianness? On big-endian architectures, this
host-endian byte slice will mix incorrectly when grouped into 64-bit words,
corrupting the NVKV stream for the GPU hardware which expects a fixed
little-endian layout.

> +        // INVARIANT: The padding ensures the total length remains a 
> multiple of
> +        // size_of::<u64>().
> +        Ok(self.0.extend_with(padded - bytes.len(), 0u8, GFP_KERNEL)?)
> +    }
> +}
[ ... ]
> +impl Deref for EncodedStream {
> +    type Target = [u64];
> +
> +    fn deref(&self) -> &Self::Target {
> +        // An empty Vec's pointer isn't necessarily aligned by 
> StreamAllocator::MIN_ALIGN.
> +        if self.0.is_empty() {
> +            return &[];
> +        }
> +
> +        // PANIC: By the type invariants the byte length is a multiple of 
> size_of::<u64>(), and
> +        // the backing buffer of a non-empty vector has at least u64 
> alignment per
> +        // StreamAllocator's minimum alignment.
> +        <[u64]>::ref_from_bytes(&self.0).expect("EncodedStream invariant 
> violated")

[Severity: High]
Can casting the host-endian byte stream directly to a slice of native-endian
u64s cause data corruption? Since the hardware expects a little-endian
layout, interpreting these bytes via ref_from_bytes on big-endian hosts will
result in functionally incorrect GPU commands.

> +    }
> +}
[ ... ]
> +impl From<Opcode> for Bounded<u64, 4> {
> +    fn from(value: Opcode) -> Self {
> +        Bounded::from_expr(value as u64)
> +    }
> +}

[Severity: Low]
Is it possible this function will fail compilation if not heuristically
inlined by the compiler? Since it delegates to Bounded::from_expr() which
uses build_assert!() on its parameter, subsystem guidelines require an
explicit #[inline(always)] annotation to ensure the optimizer can perform
constant folding and evaluate the assertion at compile time.

> diff --git a/drivers/gpu/nova-core/gsp/nvkv/encode.rs 
> b/drivers/gpu/nova-core/gsp/nvkv/encode.rs
> new file mode 100644
> index 0000000000000..6c1a9cbd90e84
> --- /dev/null
> +++ b/drivers/gpu/nova-core/gsp/nvkv/encode.rs
[ ... ]
> +        // The ARRAY32 op word has the element count. The two elements 
> follow in little endian.
> +        assert_eq!(
> +            encoded[5],
> +            Op::zeroed()
> +                .with_key(ARRAY32_KEY)
> +                .with_index(Index::new::<3>())
> +                .with_opcode(Opcode::Array32)
> +                .with_value(2u32)
> +                .into_raw()
> +        );
> +        assert_eq!(
> +            encoded[6],
> +            u64::from(ARRAY32_VALUE[1]) << 32 | u64::from(ARRAY32_VALUE[0])
> +        );

[Severity: High]
Will this test fail on big-endian hosts? The test explicitly asserts a
little-endian memory layout for the Array32 values (placing the first 32-bit
element in the lower 32 bits of the u64). On big-endian systems, the values
will be in the upper 32 bits, causing the test to fail and confirming that
the generated payloads will be unreadable by the GPU.

-- 
Sashiko AI review ยท 
https://sashiko.dev/#/patchset/[email protected]?part=4

Reply via email to