Correct.
Also, I think I figured out the how WinDbg's rdmsr command is supposed to work on ARM64. It's very strange and I'm going to try and file a bug for clarification. Also, note that this only works for live targets and not crash dumps.
Basically, when you do a rdmsr/wrmsr command the target machine dynamically builds a function to execute the instruction (c.f. KdpEncodeMsrAccess). From the ARM Architecture Reference manual Chapter D22 (AArch64 System Register Encoding), the target register for the MSR/MRS commands are encoded in bits op0, op1, CRn, CRm, and op2:
And then there's a giant table for all the registers:
These are the bits that you're specifying as the register value in the rdmsr/wrmsr commands. The way you encode them is non-intuitive though because you don't specify the Rt bits. I created this macro that I think gets you the right argument for rdmsr/wrmsr:
#define ARM64_WINDBG_SYSREG(op0, op1, crn, crm, op2) \
( ((op0) << 16) | \
((op1) << 12) | \
((crn) << 8) | \
((crm) << 4) | \
((op2) << 0) )
DWORD ttbr0_el1 = ARM64_WINDBG_SYSREG(3, 0, 2, 0, 0);
== 0x00030200
0: kd> rdmsr 0x00030200
msr[30200] = 00400000`80d45000
0: kd> ??@$prcb->ProcessorState.ArchState.Ttbr0_El1
unsigned int64 0x00400000`80d45000
DWORD sctlr_el1 = ARM64_WINDBG_SYSREG(3, 0, 1, 0, 0);
== 0x00030100
0: kd> rdmsr 0x00030100
msr[30100] = 00001000`30d0595d
0: kd> ??@$prcb->ProcessorState.ArchState.Sctlr_El1
unsigned int64 0x00001000`30d0595d
DWORD mair_el1 = ARM64_WINDBG_SYSREG(3, 0, 10, 2, 0);
== 0x00030a20
0: kd> rdmsr 0x00030a20
msr[30a20] = 444400ff`444400ff
0: kd> ??@$prcb->ProcessorState.ArchState.Mair_El1
unsigned int64 0x444400ff`444400ff
Happy for correction if anyone else wants to grovel through KdpEncodeMsrAccess and update the macro...In the meantime I'll file a doc bug and see where that gets us.