mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Gary Guo" <gary@garyguo.net>
To: "Alexandre Courbot" <acourbot@nvidia.com>, "Gary Guo" <gary@garyguo.net>
Cc: "Danilo Krummrich" <dakr@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Daniel Almeida" <daniel.almeida@collabora.com>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Boqun Feng" <boqun@kernel.org>,
	"Yury Norov" <yury.norov@gmail.com>,
	"John Hubbard" <jhubbard@nvidia.com>,
	"Alistair Popple" <apopple@nvidia.com>,
	"Joel Fernandes" <joelagnelf@nvidia.com>,
	"Timur Tabi" <ttabi@nvidia.com>, "Edwin Peer" <epeer@nvidia.com>,
	"Eliot Courtney" <ecourtney@nvidia.com>,
	"Dirk Behme" <dirk.behme@de.bosch.com>,
	"Steven Price" <steven.price@arm.com>,
	rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v7 05/10] rust: io: add IoLoc and IoWrite types
Date: Sat, 07 Mar 2026 21:10:06 +0000	[thread overview]
Message-ID: <DGWUWSDMLCTQ.1675OOTK845MA@garyguo.net> (raw)
In-Reply-To: <DGW40MO7G2B1.27TW3629TLBOD@nvidia.com>

On Sat Mar 7, 2026 at 12:05 AM GMT, Alexandre Courbot wrote:
> On Sat Mar 7, 2026 at 12:35 AM JST, Gary Guo wrote:
>> On Fri Mar 6, 2026 at 2:32 PM GMT, Alexandre Courbot wrote:
>>> On Fri Mar 6, 2026 at 10:20 PM JST, Gary Guo wrote:
>>>> I  mean not sure `at` gives me that impression at all. It would just let me know
>>>> that I am accessing it at a different location. If you omit the `MyRegArray`
>>>> part then there's no real indication that this is an array to me.
>>>
>>> `at` is a function name, we can change it - I picked it because it is
>>> short and reasonably descriptive. The point being: we have a unique
>>> function that indicates unambigously that we are using a location for
>>> an array of registers.
>>
>> Okay, maybe `at` is not the biggest issue. I just instinctively feel the usage
>> example being awkward.
>>
>> Perhaps the fact that `Reg` exist itself is awkward to me. It looks like a type
>> that exists only for things to typecheck, and not itself represent a meaningful
>> concept.
>
> After partially implementing your two-args proposal it really turns out
> the two alternatives are very similar in essence, with most of the
> differences being details like naming and scope.
>
> The one fundamental difference is that it didn't occur to me that we
> could resolve a generic argument for a function in first position of
> write using another argument, hence I went for:
>
>     bar.write(location_builder(location_info, value));
>
> but it is also possible to do
>
>     bar.write(location_builder(location_info), value);
>
> And that's really the main difference. All the rest is mostly details
> about whether `location_builder` is an associated function of a type, a
> method of a ZST, or just a module-level function. From the point of view
> of `Io`, none of this matters as long as it gets an `IoLoc` that is
> compatible with the value. IOW, each Io submodule can provide the
> location builders that make sense for it.
>
> The `Reg` thing in my previous email was just a way to provide a scope
> for these location builders, but in retrospect a module-level function
> seems better to me if we want to keep things concise. So if we turn the
> location builders into module-level methods we could have:
>
>     use kernel::io::register as reg;
>
>     bar.write(reg::at(10), SOME_ARRAY_SCRATCH::foo());
>
> Or does
>
>     bar.write(SOME_ARRAY_SCRATCH::foo(), reg::at(10));
>
> Flow better now?

I'm still generally inclined to have location at front, as it's also going to be
how projection syntax will work for structs:

    io_write!(bar, .scratch[10], foo);

or just assignment in general

    my.scratch[10] = foo;

I should also say that, my desire of having the explicit locaction is also
partly driven by the desire to eventually unify projections with the register
macro. If we would generate a struct where fields inside are registers at there
correct offset, then `io_write!(bar, .register_name, foo)` would indeed be a
canonical way of accessing such registers using I/O projection. There's no way
to simplify `my_struct.foo = Foo {}` without repeating `foo` twice :)

For context, Benno suggested in rust-lang zulip in a discussion about how it
might be possible to use field projections to replace register macro in the
future:
https://rust-lang.zulipchat.com/#narrow/channel/522311-t-lang.2Fcustom-refs/topic/custom.20virtual.20fields/near/573703808
Don't worry, the language features don't exist yet, there's no change needed to
your series :)

Probably I should mention this earlier so you see the aspect I'm coming from,
but none of this is directly related to the `register!` work you're having
today, so I was avoiding to argue with unrelated features.

>
>>
>>>
>>> You seem to reject this design because the syntax isn't obvious and
>>> natural to you at first read. We are trying to build something new, so
>>> of course if will look a bit alien at the first encounter. That's why we
>>> have documentation, and I think it is not very difficult to wrap your
>>> head around it after seeing a few examples.
>>>
>>>>
>>>> If `at` is only for array, how would you represent the case where the same type
>>>> is being used in multiple registers?
>>>
>>> That's not something that is supported by the register macro currently
>>> (probably not a big change, but not something I will do in this series).
>>>
>>> But to try and answer your question, such register types would not have
>>> an `IoLoc` implementation of their own and would need to have their
>>> location constructed explicitly. In accordance, the construction of
>>> their value would not bear any location information; thus there would be
>>> no redundancy.
>>>
>>> We do have a case that is pretty close to this with relative registers.
>>> These are accessed like this (real examples):
>>>
>>>     bar.write(Reg::of::<Gsp>(regs::NV_PFALCON_FALCON_DMACTL::zeroed()));
>>>
>>> and
>>>
>>>     bar.write(Reg::of::<Sec2>(regs::NV_PFALCON_FALCON_DMACTL::zeroed()));
>>
>> Relative registers are something that on my list to eliminate and replace with
>> projections, so I don't particular care about how it looks like.
>
> That's interesting, I thought register arrays would be easier to replace
> than relative registers, I really need to take a closer look.

Register array with stride might be tricky, although I have to say I haven't put
much thought into this yet.

>
>>
>>>
>>> But for register types that can be used at several arbitrary locations,
>>> I think this would be even simpler. The different locations would just
>>> need to implement `IoLoc<T>`, where `T` is the shared register type.
>>> Then, considering that the two-arguments version is called `write_at`,
>>> you can simply do:
>>>
>>>    bar.write_at(REG_LOCATION, reg_value);
>>
>> Having `write_at` as the name of the two-argument version is okay to me.
>
> I picked that for illustrative purposes, but `write` should be the
> version that is going to be the most used. And if we remove the value
> from the location builder, then the most used version is clearly going
> to be the two arguments one.
>
> The one argument variant would then become a shortcut - `put` sounds
> adequate to me, but `write_val` also works.

`put` sounds good. It was also the name that Gemini suggests to me when I asked
it to come up with a short and concise name for this :)

>
>>
>>>
>>> ... but this design also makes this possible:
>>>
>>>    bar.write((REG_LOCATION, reg_value));
>>
>> I considered about this, but IMO this looks awkward.
>
> Funny how you spell "elegant". :)

It's indeed quite elegant from a FP and type theorist lens. I'm not personally
objecting this, although I feel that this may looks strange to people with C
background (not sure if that's actually true, though).

>
>>
>>>
>>> Tuples of (location, value) do implement `IoLoc` themselves, so we can
>>> use this little trick to support a 2-arguments syntax with a single
>>> method.
>>>
>>>>
>>>>>
>>>>>>
>>>>>> If you want to make things more explicit you could also have
>>>>>> `bar.write(at_array(10), ...)` or something similar.
>>>>>
>>>>> Is it possible to generate an `IoLoc<T>` without having `T` mentioned
>>>>> anywhere in the call to `at_array`?
>>>>
>>>> Exactly same as the `impl IoLoc<REG> for usize`:
>>>>
>>>>     struct AtArray(usize);
>>>>
>>>>     impl IoLoc<REG> for AtArray {
>>>>         ...
>>>>     }
>>>
>>> Right, but can the correct `REG` be inferred when the call to `at_array`
>>> doesn't bear that information? The type inferred by the second argument
>>> would have to be propagated to the first. Guess I'll try and see.
>>
>> RE: inference and bounds checking issue that you mentioned in another email, I
>> think you can have
>>
>>     fn at_array(i: usize) -> Result<AtArray<T>> { .. }
>>
>> and 
>>
>>     impl IoReg<REG> for AtArray<REG> {}
>>
>> The type inference here is no different to `Reg::at`.
>
> Yes, this clearly works and then it actually becomes `RegisterArrayLoc`,
> which already exists and also implements `IoLoc`. This convergence looks
> like positive sign to me.
>
>>
>>>
>>>>
>>>>>
>>>>>>
>>>>>> For the array case I really think trying to shove everything into a single
>>>>>> argument is a footgun. The type of value in this case *doesn't* tell us the
>>>>>> location, and the location needs to be explicit.
>>>>>
>>>>>     bar.write(Reg::at(10, regs::MyRegArray::foo()))
>>>>>
>>>>> "write the constructed value at the 10th position of the `MyRegArray`
>>>>> register array"
>>>>>
>>>>> What is missing here?
>>>>
>>>> This is completely un-natural if I try to read it with fresh mind (try to forget
>>>> about implementation details for a second).
>>>
>>> That's what documentation is for. Please give it a fair chance and ask
>>> yourself: would it still look unnatural after working with it for
>>> 20 minutes?
>>>
>>>>
>>>> `MyRegArray` here is a type name that is a bitfield and not an array. `foo` returns a
>>>> single value and not an array. "at" here is saying that the register is at a
>>>> specific location and doesn't really indicate the array nature.
>>>>
>>>> This is why I insist that I would prefer an explicit location
>>>>
>>>>     bar.write(REG_ARRAY.at(10), Reg::foo())
>>>>
>>>> would have no ambiguity whatsoever about user's intent.
>>>
>>> IIUC `REG_ARRAY` would be a const ZST and `at` a method returning an
>>> `AtArray(usize)`? I still have doubts that its generic type could be
>>> inferred automatically but it's worth giving it a go.
>>>
>>> If that works, then I assume fixed register writes would look like
>>>
>>>     bar.write(FIXED, Reg::foo());
>>>
>>> Unless we have a specialized `write` variant for them.
>>
>> That, or `()` as I mentioned.
>
> Wouldn't it look... awkward? :)
>
> But if we can agree on
>
>     bar.put(Reg::foo());
>
> or even
>
>     bar.write_val(Reg::foo());

I'm okay with either.

>
> Then I believe we are getting close to something that can make everyone
> happy (pending Danilo's blessing). The `()` syntax can also be supported
> for generic code.

Yep, if we want to support both the `put` can just be a sugar

    fn put<T>(&self, value: T) where (): IoLoc<T> + ... {
        self.write((), value)
    }

Best,
Gary

>
> I'll try to speedrun the remainder of the implementation and send a new
> revision for review, but AFAICT this ticks all the boxes.


  reply	other threads:[~2026-03-07 21:10 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-24 14:21 [PATCH v7 00/10] rust: add `register!` macro Alexandre Courbot
2026-02-24 14:21 ` [PATCH v7 01/10] rust: enable the `generic_arg_infer` feature Alexandre Courbot
2026-02-24 14:21 ` [PATCH v7 02/10] rust: num: add `shr` and `shl` methods to `Bounded` Alexandre Courbot
2026-02-24 14:21 ` [PATCH v7 03/10] rust: num: add `into_bool` method " Alexandre Courbot
2026-02-24 14:21 ` [PATCH v7 04/10] rust: num: make Bounded::get const Alexandre Courbot
2026-02-27 12:33   ` Gary Guo
2026-02-24 14:21 ` [PATCH v7 05/10] rust: io: add IoLoc and IoWrite types Alexandre Courbot
2026-02-27 18:02   ` Gary Guo
2026-02-27 18:16     ` Danilo Krummrich
2026-02-28  0:33     ` Alexandre Courbot
2026-03-01 15:11       ` Gary Guo
2026-03-02  1:44         ` Alexandre Courbot
2026-03-02 12:53           ` Gary Guo
2026-03-02 13:12             ` Danilo Krummrich
2026-03-02 13:39               ` Gary Guo
2026-03-03  8:14                 ` Alexandre Courbot
2026-03-03  8:31                   ` Alexandre Courbot
2026-03-03 14:55                     ` Alexandre Courbot
2026-03-03 15:05                       ` Gary Guo
2026-03-04 16:18                       ` Danilo Krummrich
2026-03-04 18:39                         ` Gary Guo
2026-03-04 18:58                           ` Gary Guo
2026-03-04 19:19                             ` John Hubbard
2026-03-04 19:53                               ` Danilo Krummrich
2026-03-04 19:57                                 ` John Hubbard
2026-03-04 20:05                                 ` Gary Guo
2026-03-04 19:38                             ` Danilo Krummrich
2026-03-04 19:48                               ` Gary Guo
2026-03-04 20:37                                 ` Danilo Krummrich
2026-03-04 21:13                                   ` Gary Guo
2026-03-04 21:38                                     ` Danilo Krummrich
2026-03-04 21:42                                       ` Danilo Krummrich
2026-03-04 22:15                                       ` Gary Guo
2026-03-04 22:22                                         ` Danilo Krummrich
2026-03-06  5:37                                         ` Alexandre Courbot
2026-03-06  7:47                                           ` Alexandre Courbot
2026-03-06 10:42                                           ` Gary Guo
2026-03-06 11:10                                             ` Alexandre Courbot
2026-03-06 11:35                                               ` Gary Guo
2026-03-06 12:50                                                 ` Alexandre Courbot
2026-03-06 13:20                                                   ` Gary Guo
2026-03-06 14:32                                                     ` Alexandre Courbot
2026-03-06 14:52                                                       ` Alexandre Courbot
2026-03-06 15:10                                                       ` Alexandre Courbot
2026-03-06 15:35                                                         ` Alexandre Courbot
2026-03-06 15:35                                                       ` Gary Guo
2026-03-07  0:05                                                         ` Alexandre Courbot
2026-03-07 21:10                                                           ` Gary Guo [this message]
2026-03-07 21:40                                                             ` Danilo Krummrich
2026-03-08 11:43                                                               ` Alexandre Courbot
2026-03-08 11:35                                                             ` Alexandre Courbot
2026-03-04 18:53                         ` Gary Guo
2026-03-04 22:19   ` Gary Guo
2026-03-05 11:02     ` Alexandre Courbot
2026-02-24 14:21 ` [PATCH v7 06/10] rust: io: use generic read/write accessors for primitive accesses Alexandre Courbot
2026-02-27 18:04   ` Gary Guo
2026-02-24 14:21 ` [PATCH v7 07/10] rust: io: add `register!` macro Alexandre Courbot
2026-02-24 14:21 ` [PATCH v7 08/10] sample: rust: pci: use " Alexandre Courbot
2026-02-24 14:21 ` [PATCH FOR REFERENCE v7 09/10] gpu: nova-core: use the kernel " Alexandre Courbot
2026-02-24 14:21 ` [PATCH v7 10/10] RFC: rust: io: allow fixed register values directly in `write` Alexandre Courbot
2026-02-25 11:58 ` [PATCH v7 00/10] rust: add `register!` macro Dirk Behme
2026-02-25 13:50   ` Alexandre Courbot
2026-02-26 12:01     ` Dirk Behme
2026-02-27 23:30       ` Alexandre Courbot

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=DGWUWSDMLCTQ.1675OOTK845MA@garyguo.net \
    --to=gary@garyguo.net \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=aliceryhl@google.com \
    --cc=apopple@nvidia.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=dirk.behme@de.bosch.com \
    --cc=ecourtney@nvidia.com \
    --cc=epeer@nvidia.com \
    --cc=jhubbard@nvidia.com \
    --cc=joelagnelf@nvidia.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=steven.price@arm.com \
    --cc=tmgross@umich.edu \
    --cc=ttabi@nvidia.com \
    --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®