On 3/6/26 06:47, Peter Maydell wrote:
There are a couple of ways I can see that we could try to fix this:
(A) We could insist that every target's CPUFooState (env struct)
must be shallow-copiable, and anything that isn't (pointers, etc)
needs to be moved out to its FOOCPU (QOM CPU object struct).
Then we could let targets implement any per-target copying specifics
in some function in linux-user/$ARCH/ that we call from cpu_copy()
after doing the memcpy(). This would be painful if there are any
targets that have something non shallow-copiable that they want
access to directly from generated code, which has the env pointer
but not the CPU object struct.
(B) We could standardize the "end_reset_fields" convention that
some targets have in their env struct, where an empty struct
marks the end of the point in the struct where fields can be
reset by zeroing them. If they can be reset by zeroing they can
also be safely shallow copied with memcpy(). We could then let the
target handle anything else via some target hook as above.
This would require a lot of targets having this field marker added,
which could be a pain if they don't have their structs ordered in
a convenient way for this.
(C) We could say that trying to write generic code that can
copy a target-specific structure is a fool's errand, and require
the targets to implement it entirely themselves (only copying the
stuff in the common CPU base class in common code). If a plain
memcpy() works for them then their implementation can be simple.
Any preferences ?
The fixup function, as required by A and B, makes me prefer C.
Surely it's clearer to have
cc->copy_env(new, old);
than
memcpy(new, old, some_size);
cc->fixup_env(new);
especially with the computation of some_size containing some
amount of target-specific peril.
r~