From: Alexandre Courbot <[email protected]> `LogBuffer` is the entity we ultimately want to dump through debugfs. Provide a simple implementation of `BinaryWriter` for it, albeit it might not cut the safety requirements.
Signed-off-by: Alexandre Courbot <[email protected]> Signed-off-by: Timur Tabi <[email protected]> --- drivers/gpu/nova-core/gsp.rs | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs index 766fd9905358..273327c33aa7 100644 --- a/drivers/gpu/nova-core/gsp.rs +++ b/drivers/gpu/nova-core/gsp.rs @@ -3,6 +3,7 @@ mod boot; use kernel::{ + debugfs, device, dma::{ CoherentAllocation, @@ -117,6 +118,45 @@ pub(crate) struct Gsp { rmargs: CoherentAllocation<GspArgumentsCached>, } +impl debugfs::BinaryWriter for LogBuffer { + fn write_to_slice( + &self, + writer: &mut kernel::uaccess::UserSliceWriter, + offset: &mut kernel::fs::file::Offset, + ) -> Result<usize> { + if offset.is_negative() { + return Err(EINVAL); + } + + let offset_val: usize = (*offset).try_into().map_err(|_| EINVAL)?; + let len = self.0.count(); + + if offset_val >= len { + return Ok(0); + } + + let count = (len - offset_val).min(writer.len()); + + // SAFETY: + // - `start_ptr()` returns a valid pointer to a memory region of `count()` bytes, + // as guaranteed by the `CoherentAllocation` invariants. + // - `len` equals `self.0.count()`, so the pointer is valid for `len` bytes. + // - `offset_val < len` is guaranteed by the check above. + // - `count = (len - offset_val).min(writer.len())`, so `offset_val + count <= len`. + unsafe { writer.write_buffer(self.0.start_ptr(), len, offset_val, count)? }; + + *offset += count as i64; + Ok(count) + } +} + +// SAFETY: `LogBuffer` only provides shared access to the underlying `CoherentAllocation`. +// GSP may write to the buffer concurrently regardless of CPU access, so concurrent reads +// from multiple CPU threads do not introduce any additional races beyond what already +// exists with the device. Reads may observe partially-written log entries, which is +// acceptable for debug logging purposes. +unsafe impl Sync for LogBuffer {} + impl Gsp { // Creates an in-place initializer for a `Gsp` manager for `pdev`. pub(crate) fn new(pdev: &pci::Device<device::Bound>) -> impl PinInit<Self, Error> + '_ { -- 2.52.0
