I read through mmu_context.h and the threads from November/December
2010 a couple of times, and I'm starting to think Maksim's original
approach (don't reset asid_cache(cpu) when warm-restarting a CPU)
makes the most sense.
The basic issue is that we want to assign unique, strictly increasing
values to each mm's cpu_context(cpu, mm). The per-cpu counter starts
at ASID_FIRST_VERSION (0x100 on R4K), and counts up. Assigning a new
mm the same ASID value as an existing mm on the same CPU is illegal.
Two obvious ways to meet this requirement when hotplugging CPUs are:
Option #1: Retain the asid_cache(cpu) value across warm restarts.
This is simple and inexpensive. We pick up where we left off, and
whatever existing cpu_context(cpu, mm) values are out there do not
cause any trouble.
I believe Maksim's original logic (assign ASID_FIRST_VERSION, a
nonzero number, if asid_cache(cpu) == 0) would work correctly as
written, because cpu_data is an array in .bss . It will be 0 until
the CPU is booted, and get_new_mmu_context() ensures that it will
never be 0 again after that.
Kevin K brought up the idea of a warm restart bitmask so the code
could tell whether asid_cache(cpu) was valid. I'm not sure that this
would be required.
I think we can also get away with not explicitly preserving EntryHi,
since switch_mm() and activate_mm() will set it anyway.
Option #2: When warm restarting a CPU, set asid_cache(cpu) to
ASID_FIRST_VERSION again. And at some point (cpu_up or cpu_down),
iterate through all processes to set cpu_context(cpu, mm) to something
that will not conflict with a newly assigned ASID. This is what the
most recent patch did. It gets the job done, but it's more work than
what is really needed.
Please let me know your thoughts...