rod wrote:
Provide different page table mappings for different cores and store different values in the same virtual address, then read those values.
I believe this will require one version of every process's address space for each cpu. In particular, one cpu specific page table must be created for each address translation level. And on-the-fly changes to such address space will get complicated as well.
rod wrote:
Are there any other methods?
Honestly, I am mostly spectator here (for educational purposes), but skimming over the Linux kernel sources I see that the x86-64 ISR uses the "swapgs" instruction on entry. This changes the GS descriptor's base to a value controlled through an MSR. The GS descriptor is pointed to a per-cpu structure in kernel mode (their ABI you could say), which means that the kernel can store all sorts of cpu-specific information as fields in it, including a CPU id (which you want), pointers to per-cpu scheduler queues, etc. You can also get the GS register base or the cpu id from your ISR stack, assuming it was configured through the interrupt stack table individually for each cpu. Essentially, you either need to get the kernel stack from the per-cpu structures or you need to get the per-cpu structures from the kernel stack. But either way, once you end up with a per-cpu state, you will receive a "cache" of the cpu id as a field in the per-cpu data. The instruction is actually mentioned in the
wiki.
Now, this may not be actually be as reliable as some of the methods you have mentioned. The technique here assumes that the per-cpu structure is consistent between ISR invocations.
Edit: Korona gave you the answer already, but I will leave my answer as well, in case there is something useful in it.