When the CPU is in kernel mode, can it read and write to any register, or are there some registers that are inaccessible even in kernel mode?
1 Answers
On x86, there aren't banked registers so all the registers are architecturally visible at the same time.
And yes, in kernel mode (ring 0) x86 can write any register. (As long as the kernel is running in 64-bit mode, otherwise it can't access x/ymm8..16 or zmm8..31, or r8..r15).
And yes, a kernel that switches to 32-bit mode after entering the kernel from 64-bit userspace is possible; Solaris x86-64 apparently did this, and MacOS X used to do this for compatibility with 32-bit kernel drivers. On machines with less than 4GB of RAM and smaller caches, using smaller pointers in the kernel has some benefits and the downsides maybe aren't as huge.
wrmsr (Write Model-Specific Register) requires kernel mode. So does rdmsr to read MSRs. So unlike the integer and vector regs (rax..rsi/r8..r15 and xmm0..15), which user-space can freely use, there are registers that only the kernel can modify.
There might possibly be some model-specific regs that are only accessible in system-management mode. (sometimes called ring -1) I don't know, I haven't read much about SMM. And/or registers associated with SGX (used for "enclaves), which again I haven't looked into.
There might also be some read-only MSRs that you can never write with wrmsr. IDK if that's what you mean, or if you're only counting registers that are normally considered part of the architectural state that's saved/restored on context switches, like the general-purpose integer registers. All of those regs are writeable in any mode, even segment regs.
The internal segment base/limit registers are not directly readable, but in 64-bit long mode they're fixed at base=0 / limit=-1 except for FS and GS. But those bases are accessible with rdmsr/wrmsr on MSR_GS_BASE / MSR_FS_BASE.
The FSGSBASE ISA extension added wrfsbase etc. which does let you more directly read/write the FS and GS bases, more efficiently than the MSR. (Either way, the kernel doesn't have to actually modify a GDT or LDT entry and reload fs to update the fs base for thread-local storage). Detail about MSR_GS_BASE in linux x86 64
But I don't think the cs/ds/es/ss base/limit are exposed via MSRs, and those are relevant for 32-bit protected mode. (Or for switching back to real mode to create "unreal" mode.)
- 328,167
- 45
- 605
- 847
-
What about the secure enclave stuff? – fuz Apr 18 '19 at 13:19
-
@fuz: Does SGX have its own registers, too? I've never really looked into it. But good point, I forgot to mention that as well as SMM. – Peter Cordes Apr 18 '19 at 13:22
-
1Some other registers that cannot be read or written directly are the internal segment base and segment limit registers. This is used for unreal mode for example. – fuz Apr 18 '19 at 14:15
-
@fuz: Good point, describing those as "registers" not "caches" is accurate. The FSGSBASE ISA extension added [`wrfsbase`](https://www.felixcloutier.com/x86/wrfsbase:wrgsbase) etc. which does let you directly read/write the FS and GS bases, though. And even without that, they're accessible via MSRs. And in long mode, the other segments are fixed at base=0 limit=-1 – Peter Cordes Apr 18 '19 at 14:26
-
@fuz: bedtime for me, if you see anything else you want to add, feel free to edit. (Or of course post your own answer.) – Peter Cordes Apr 18 '19 at 14:33
-
1I don't know about Solaris but the MacOS kernel did this. [How come a 32 bit kernel can run a 64 bit binary?](https://stackoverflow.com/q/49934/995714) – phuclv Apr 18 '19 at 16:19