Il mer 11 dic 2024, 08:41 Zhao Liu <zhao1....@intel.com> ha scritto:

> And since we are talking about the safety of INSTANCE_INIT, I think we
> should add some safety guidelines here, like:
>  * Proper Initialization of pointers and references
>  * Explicit initialization of Non-Zero Fields
>  * In placed memory region is correctly initialized.
>

Yes that's pretty much it.

(Or do you have any additional or clearer guidelines?)
>
> This could be the reference when adding SAFETY comment for the device's
> own `unsafe` init(). :-)
>
> And this is also a good explanation to distinguish between initialization
> in init() and realize(). For example, HPET attempts to initialize the
> timer array in realize().
>

Generally:

- embedded objects will have to be initialized in instance_init unless they
are Options

- sysbus_init_irq and sysbus_init_mmio can be called in both instance_init
and instance_post_init for now, but they will have to be in post_init once
the signature of init changes to return impl PinInit

- if you don't need properties you can choose between post_init and
realize, if you need properties you need to initialize in realize (and
then, unlike C, you might need to explicitly allow the pre-realize state;
for example using Option<&...> instead of just a reference; or Vec<>
instead of an array).

>
> > The way that this will become safe is to use the pinned_init crate from
> > Linux: instance_init returns the initialization as an "impl
> PinInit<Self>",
>
> Then do we need to place OBJECT in some suitable memory location (Box or
> something) for Rust implementation?
>

Allocation is still done by the C code, so I am not sure I understand the
question. Rust code allocates QOM objects with object_new() so they are
malloc-ed. I discussed it with Manos some time ago and in principle you
could use a Box (QOM supports custom freeing functions) but it's a bit
complex because the freeing function would have to free the memory without
dropping the contents of the Box (the drop is done by QOM via
instance_finalize).

If you want to allocate the HPETTimers at realize time, I think you can
place them in a Vec. I think you won't need NonNull for this, but I am not
100% sure. Alternatively if you want to always prepare all MAX_TIMERS of
them and then only use a subset, you can use an array.

Either way, probably it makes sense for you to have an "fn
timers_iter(&self) -> impl Iter<Item = &BqlRefCell<HPETTimer>>" in
HPETState, or something like that. Then you can easily use for loops to
walk all timers between 0 and self.num_timers-1.

Paolo

> and then instance_post_init can run with a &self.  Until then, however,
> > instance_init has to remain unsafe.
>
> Thanks for sharing! It's a very reasonable direction.
>
> Regards,
> Zhao
>
>

Reply via email to