mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Joel Fernandes <joelagnelf@nvidia.com>
To: Alexandre Courbot <acourbot@nvidia.com>,
	linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
	dri-devel@lists.freedesktop.org, dakr@kernel.org
Cc: Alistair Popple <apopple@nvidia.com>,
	Miguel Ojeda <ojeda@kernel.org>,
	Alex Gaynor <alex.gaynor@gmail.com>,
	Boqun Feng <boqun.feng@gmail.com>, Gary Guo <gary@garyguo.net>,
	bjorn3_gh@protonmail.com, Benno Lossin <lossin@kernel.org>,
	Andreas Hindborg <a.hindborg@kernel.org>,
	Alice Ryhl <aliceryhl@google.com>,
	Trevor Gross <tmgross@umich.edu>,
	David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
	Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
	Maxime Ripard <mripard@kernel.org>,
	Thomas Zimmermann <tzimmermann@suse.de>,
	John Hubbard <jhubbard@nvidia.com>, Timur Tabi <ttabi@nvidia.com>,
	joel@joelfernandes.org, Elle Rhumsaa <elle@weathered-steel.dev>,
	Yury Norov <yury.norov@gmail.com>,
	Daniel Almeida <daniel.almeida@collabora.com>,
	Andrea Righi <arighi@nvidia.com>,
	nouveau@lists.freedesktop.org
Subject: Re: [PATCH v6 5/5] rust: bitfield: Add KUNIT tests for bitfield
Date: Mon, 6 Oct 2025 15:38:06 -0400	[thread overview]
Message-ID: <6cc43cd3-5f67-49cf-bafb-67a0a22368cf@nvidia.com> (raw)
In-Reply-To: <DDB69ONCWBEJ.1KGWC6H2VG2CE@nvidia.com>



On 10/6/2025 6:37 AM, Alexandre Courbot wrote:
> On Sat Oct 4, 2025 at 12:47 AM JST, Joel Fernandes wrote:
>> Add KUNIT tests to make sure the macro is working correctly.
>>
>> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
>> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
>> ---
>>  rust/kernel/bitfield.rs | 323 ++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 323 insertions(+)
>>
>> diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs
>> index 09cd5741598c..f0e341a1a979 100644
>> --- a/rust/kernel/bitfield.rs
>> +++ b/rust/kernel/bitfield.rs
>> @@ -329,3 +329,326 @@ fn default() -> Self {
>>          }
>>      };
>>  }
>> +
>> +#[::kernel::macros::kunit_tests(kernel_bitfield)]
>> +mod tests {
>> +    use core::convert::TryFrom;
>> +
>> +    // Enum types for testing => and ?=> conversions
>> +    #[derive(Debug, Default, Clone, Copy, PartialEq)]
>> +    enum MemoryType {
>> +        #[default]
>> +        Unmapped = 0,
>> +        Normal = 1,
>> +        Device = 2,
>> +        Reserved = 3,
>> +    }
>> +
>> +    impl TryFrom<u8> for MemoryType {
>> +        type Error = u8;
>> +        fn try_from(value: u8) -> Result<Self, Self::Error> {
>> +            match value {
>> +                0 => Ok(MemoryType::Unmapped),
>> +                1 => Ok(MemoryType::Normal),
>> +                2 => Ok(MemoryType::Device),
>> +                3 => Ok(MemoryType::Reserved),
>> +                _ => Err(value),
>> +            }
>> +        }
>> +    }
>> +
>> +    impl From<MemoryType> for u64 {
>> +        fn from(mt: MemoryType) -> u64 {
>> +            mt as u64
>> +        }
>> +    }
>> +
>> +    #[derive(Debug, Default, Clone, Copy, PartialEq)]
>> +    enum Priority {
>> +        #[default]
>> +        Low = 0,
>> +        Medium = 1,
>> +        High = 2,
>> +        Critical = 3,
>> +    }
>> +
>> +    impl From<u8> for Priority {
>> +        fn from(value: u8) -> Self {
>> +            match value & 0x3 {
>> +                0 => Priority::Low,
>> +                1 => Priority::Medium,
>> +                2 => Priority::High,
>> +                _ => Priority::Critical,
>> +            }
>> +        }
>> +    }
>> +
>> +    impl From<Priority> for u16 {
>> +        fn from(p: Priority) -> u16 {
>> +            p as u16
>> +        }
>> +    }
>> +
>> +    bitfield! {
>> +        struct TestPageTableEntry(u64) {
>> +            0:0       present     as bool;
>> +            1:1       writable    as bool;
>> +            11:9      available   as u8;
>> +            13:12     mem_type    as u8 ?=> MemoryType;
>> +            17:14     extended_type as u8 ?=> MemoryType;  // For testing failures
>> +            51:12     pfn         as u64;
> 
> Is the overlap with `mem_type` and `extended_type` on purpose? 

Yes, here I was testing the failure mode of ?=> without having to introduce a
new enum type. But I could just do so with mem_type by adding more bits to it,
so I'll do that and remove extended_type.

> It looks strange to me that the PFN also includes the memory type.

I agree with this (even though these structs are just approximately accurate and
for testing purposes). Since we're testing overlap already in later tests, I
will just remove it from this test.

Following is the new struct now, hope it looks ok:

    bitfield! {
        struct TestPageTableEntry(u64) {
            0:0       present     as bool;
            1:1       writable    as bool;
            11:9      available   as u8;
            15:12     mem_type    as u8 ?=> MemoryType;
            51:16     pfn         as u64;
            61:52     available2  as u16;
        }
    }

>> +            51:12     pfn_overlap as u64;
> 
> If `pfn` needs to be adjusted then I guess this one also needs to be.
> 
>> +            61:52     available2  as u16;
>> +        }
>> +    }
>> +
>> +    bitfield! {
>> +        struct TestControlRegister(u16) {
>> +            0:0       enable      as bool;
>> +            3:1       mode        as u8;
>> +            5:4       priority    as u8 => Priority;
>> +            7:4       priority_nibble as u8;
>> +            15:8      channel     as u8;
>> +        }
>> +    }
>> +
>> +    bitfield! {
>> +        struct TestStatusRegister(u8) {
>> +            0:0       ready       as bool;
>> +            1:1       error       as bool;
>> +            3:2       state       as u8;
>> +            7:4       reserved    as u8;
>> +            7:0       full_byte   as u8;  // For entire register
>> +        }
>> +    }
>> +
>> +    #[test]
>> +    fn test_single_bits() {
>> +        let mut pte = TestPageTableEntry::default();
>> +
>> +        assert!(!pte.present());
>> +        assert!(!pte.writable());
>> +        assert_eq!(u64::from(pte), 0x0);
>> +
>> +        pte = pte.set_present(true);
>> +        assert!(pte.present());
>> +        assert_eq!(u64::from(pte), 0x1);
>> +
>> +        pte = pte.set_writable(true);
>> +        assert!(pte.writable());
>> +        assert_eq!(u64::from(pte), 0x3);
>> +
>> +        pte = pte.set_writable(false);
>> +        assert!(!pte.writable());
>> +        assert_eq!(u64::from(pte), 0x1);
>> +
>> +        assert_eq!(pte.available(), 0);
>> +        pte = pte.set_available(0x5);
>> +        assert_eq!(pte.available(), 0x5);
>> +        assert_eq!(u64::from(pte), 0xA01);
>> +    }
>> +
>> +    #[test]
>> +    fn test_range_fields() {
>> +        let mut pte = TestPageTableEntry::default();
>> +        assert_eq!(u64::from(pte), 0x0);
>> +
>> +        pte = pte.set_pfn(0x123456);
>> +        assert_eq!(pte.pfn(), 0x123456);
>> +        // Test overlapping field reads same value
>> +        assert_eq!(pte.pfn_overlap(), 0x123456);
>> +        assert_eq!(u64::from(pte), 0x123456000);
>> +
>> +        pte = pte.set_available(0x7);
>> +        assert_eq!(pte.available(), 0x7);
>> +        assert_eq!(u64::from(pte), 0x123456E00);
>> +
>> +        pte = pte.set_available2(0x3FF);
>> +        assert_eq!(pte.available2(), 0x3FF);
>> +        assert_eq!(u64::from(pte), 0x3FF0000123456E00);
>> +
>> +        // Test TryFrom with ?=> for MemoryType
>> +        pte = pte.set_mem_type(MemoryType::Device);
>> +        assert_eq!(pte.mem_type(), Ok(MemoryType::Device));
>> +        assert_eq!(u64::from(pte), 0x3FF0000123456E00);
>> +
>> +        pte = pte.set_mem_type(MemoryType::Normal);
>> +        assert_eq!(pte.mem_type(), Ok(MemoryType::Normal));
>> +        assert_eq!(u64::from(pte), 0x3FF0000123455E00);
>> +
>> +        // Test all valid values for mem_type
>> +        pte = pte.set_mem_type(MemoryType::Reserved);
>> +        assert_eq!(pte.mem_type(), Ok(MemoryType::Reserved));
>> +        assert_eq!(u64::from(pte), 0x3FF0000123457E00);
>> +
>> +        // Test failure case using extended_type field which has 4 bits (0-15)
>> +        // MemoryType only handles 0-3, so values 4-15 should return Err
>> +        let mut raw = pte.into();
>> +        // Set bits 17:14 to 7 (invalid for MemoryType)
>> +        raw = (raw & !::kernel::bits::genmask_u64(14..=17)) | (0x7 << 14);
>> +        let invalid_pte = TestPageTableEntry(raw);
>> +        // Should return Err with the invalid value
>> +        assert_eq!(invalid_pte.extended_type(), Err(0x7));
>> +
>> +        // Test a valid value after testing invalid to ensure both cases work
>> +        // Set bits 17:14 to 2 (valid: Device)
>> +        raw = (raw & !::kernel::bits::genmask_u64(14..=17)) | (0x2 << 14);
>> +        let valid_pte = TestPageTableEntry(raw);
>> +        assert_eq!(valid_pte.extended_type(), Ok(MemoryType::Device));
>> +
>> +        let max_pfn = ::kernel::bits::genmask_u64(0..=39);
>> +        pte = pte.set_pfn(max_pfn);
>> +        assert_eq!(pte.pfn(), max_pfn);
>> +        assert_eq!(pte.pfn_overlap(), max_pfn);
>> +    }
>> +
>> +    #[test]
>> +    fn test_builder_pattern() {
>> +        let pte = TestPageTableEntry::default()
>> +            .set_present(true)
>> +            .set_writable(true)
>> +            .set_available(0x7)
>> +            .set_pfn(0xABCDEF)
>> +            .set_mem_type(MemoryType::Reserved)
>> +            .set_available2(0x3FF);
>> +
>> +        assert!(pte.present());
>> +        assert!(pte.writable());
>> +        assert_eq!(pte.available(), 0x7);
>> +        assert_eq!(pte.pfn(), 0xABCDEF);
>> +        assert_eq!(pte.pfn_overlap(), 0xABCDEF);
>> +        assert_eq!(pte.mem_type(), Ok(MemoryType::Reserved));
>> +        assert_eq!(pte.available2(), 0x3FF);
> 
> Maybe check the raw value here as well, although I guess the previous
> test already covered this anyway.
> 
> With these points confirmed,
> 
> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Thanks! I will resend just this patch as a reply-to this patch (hope that's Ok).

 - Joel



  reply	other threads:[~2025-10-06 19:38 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-03 15:47 [PATCH v6 0/5] Introduce bitfield and move register macro to rust/kernel/ Joel Fernandes
2025-10-03 15:47 ` [PATCH v6 1/5] nova-core: bitfield: Move bitfield-specific code from register! into new macro Joel Fernandes
2025-10-06 17:56   ` Edwin Peer
2025-10-07  6:49     ` Alexandre Courbot
2025-10-03 15:47 ` [PATCH v6 2/5] nova-core: bitfield: Add support for different storage widths Joel Fernandes
2025-10-03 15:47 ` [PATCH v6 3/5] nova-core: bitfield: Add support for custom visiblity Joel Fernandes
2025-10-03 15:47 ` [PATCH v6 4/5] rust: Move register and bitfield macros out of Nova Joel Fernandes
2025-10-06 10:38   ` Alexandre Courbot
2025-10-09  6:59   ` Dirk Behme
2025-10-09 11:16     ` Danilo Krummrich
2025-10-09 11:28       ` Alexandre Courbot
2025-10-09 12:54         ` Danilo Krummrich
2025-11-01 18:51         ` Dirk Behme
2025-11-02  3:00           ` Alexandre Courbot
2025-11-13  6:26             ` Dirk Behme
2025-10-10  7:28       ` Dirk Behme
2025-10-22 18:40   ` Beata Michalska
2025-10-22 19:37     ` Joel Fernandes
2025-10-23 13:55       ` Beata Michalska
2025-10-23 14:07         ` Danilo Krummrich
2025-10-23 21:47         ` Joel Fernandes
2025-10-23 21:50           ` Joel Fernandes
2025-10-27  9:06           ` Beata Michalska
2025-10-27  9:56             ` Danilo Krummrich
2025-10-27 15:05               ` Beata Michalska
2025-10-03 15:47 ` [PATCH v6 5/5] rust: bitfield: Add KUNIT tests for bitfield Joel Fernandes
2025-10-06 10:37   ` Alexandre Courbot
2025-10-06 19:38     ` Joel Fernandes [this message]
2025-10-06 20:36   ` [PATCH v7] " Joel Fernandes
2025-10-06 18:05 ` [PATCH v6 0/5] Introduce bitfield and move register macro to rust/kernel/ Edwin Peer
2025-10-06 22:29 ` Yury Norov
2025-10-07 10:36   ` Alexandre Courbot
2025-10-07 10:42     ` Miguel Ojeda
2025-10-07 13:20       ` Alexandre Courbot
2025-10-07 16:06         ` Yury Norov
2025-10-07 16:12         ` Miguel Ojeda
2025-10-07 13:16     ` Danilo Krummrich
2025-10-07 21:08       ` Joel Fernandes
2025-10-07 22:08         ` Danilo Krummrich
2025-10-08 14:28           ` Yury Norov
2025-10-08 15:00             ` Danilo Krummrich
2025-10-07 15:41     ` Yury Norov
2025-10-07 21:41       ` Daniel Almeida
2025-10-08 15:49         ` Yury Norov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6cc43cd3-5f67-49cf-bafb-67a0a22368cf@nvidia.com \
    --to=joelagnelf@nvidia.com \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=airlied@gmail.com \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=apopple@nvidia.com \
    --cc=arighi@nvidia.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=elle@weathered-steel.dev \
    --cc=gary@garyguo.net \
    --cc=jhubbard@nvidia.com \
    --cc=joel@joelfernandes.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mripard@kernel.org \
    --cc=nouveau@lists.freedesktop.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=simona@ffwll.ch \
    --cc=tmgross@umich.edu \
    --cc=ttabi@nvidia.com \
    --cc=tzimmermann@suse.de \
    --cc=yury.norov@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®