An astute reader might realize that computing the cache line on every
invocation is not enough for user space code: It can happen that a process
gets scheduled on a different CPU while executing the __clear_cache
function with a certain cache line size, where it might not be valid
anymore. Therefore, we have to try to figure out a global minimum of the cache line sizes across all CPUs.
Wouldn't this mean they'd always just end up clearing half the cache line for larger core anyway?In theory I think you could just invalidate the addresses byte for byte, ignoring the cache line size, but I assume the performance hit would be noticeable.
Along similar lines, if you have an optimized routine using specific CPU instructions, you don't want to call CPUID (or equivalent) on every call to find out if you have those instructions; you want to call it once and cache the answer. If it can return different answers on different CPUs in the same system, you need to use a different mechanism instead, such as asking the OS for the least common denominator features of available CPUs, or notifying the OS that you need to run on one of the more capable CPUs that has the feature you need.
You'll choose a lowest common denominator of features sets.
Also, for this specific case, I doubt migration will keep around the contents of the cache lines and their 'dirty' bits (corollary: it will be possible to reliably detect a move, if one is willing to continuously run code that detects cache-line timing differences)
The only real fix is to do what they are doing -- always use the smallest line size of the system, regardless of which core you are running on.
(This is all documented in the v8 ARM ARM section "Synchronization requirements for AArch64 System Registers".)