2

Aarch64 architecture has the following registers, that contain physical base addresses for the virtual-to-physical translation tables for different exception levels:

TTBR0_EL1, TTBR1_EL1, TTBR0_EL2, TTBR0_EL3

I can't seem to find how to retrieve their values in WinDbg when I'm reviewing a full memory kernel crash dump, or if I'm attached to a live Windows OS kernel.

PS. One can do it in assembly, as follows:

mrs    x0,   ttbr0_el1     ;    read TTBR0_EL1 register into X0 general purpose register

1 Answer 1

1

UPDATE 2: short answer is rdmsr 0x00030200. The harder question is how to determine the "MSR" values? this is done by using ARM64_WINDBG_SYSREG macro which is defined as follows:

    #define ARM64_WINDBG_SYSREG(op0, op1, crn, crm, op2) \
            ( ((op0) << 16) | \
              ((op1) << 12) | \
              ((crn) << 8) | \
              ((crm) << 4) | \
              ((op2) << 0) )

or in python:

def ARM64_WINDBG_SYSREG(op0, op1, crn, crm, op2):
    return ( ((op0) << 16) | ((op1) << 12) | ((crn) << 8) | ((crm) << 4) | ((op2) << 0) )

And by using the following arguments the result is 0x30200:

Name        Op0 CRn Op1 CRm Op2 Width
TTBR0_EL1   3   c2  0   c0  0   64

As mentioned before in the comments the parameters for this macro for other System Registers or "MSRs" can be found here.

UPDATE 1: There is also an option of looking at a cached version of the registers values through (since the registers don't change after initialization during boot then this is not a bad option):

KPCR->KPRCB->ProcessorState->ArchState

kd> !pcr
KPCR for Processor 0 at fffff803ed4a0000:
    Major 1 Minor 1
Panic Stack 00000000
Dpc Stack 00000000
Irql addresses:
    Mask    fffff803ed4a0000
    Table   fffff803ed4a0000
    Routine fffff803ed4a0000
kd> dt nt!_KARM64_ARCH_STATE fffff803ed4a0000+0x980+0x40+0xa0
   +0x000 Midr_El1         : 0x410fd4c0
   +0x008 Sctlr_El1        : 0x30d0595d
   +0x010 Actlr_El1        : 0
   +0x018 Cpacr_El1        : 0x300000
   +0x020 Tcr_El1          : 0x00000015`b5513511
   +0x028 Ttbr0_El1        : 0x00010000`008ef000
   +0x030 Ttbr1_El1        : 0x00010000`008ef800
   +0x038 Esr_El1          : 0xf200f002
   +0x040 Far_El1          : 0xffff8180`ed005540
   +0x048 Pmcr_El0         : 0
   +0x050 Pmcntenset_El0   : 0
   +0x058 Pmccntr_El0      : 0
   +0x060 Pmxevcntr_El0    : [31] 0
   +0x158 Pmxevtyper_El0   : [31] 0
   +0x250 Pmovsclr_El0     : 0
   +0x258 Pmselr_El0       : 0
   +0x260 Pmuserenr_El0    : 0
   +0x268 Mair_El1         : 0x444400ff`444400ff
   +0x270 Vbar_El1         : 0xfffff803`f1a02800

Original Answer:

Short answer is, AFAIK there isn't currently a way to do that.

I think it might be implemented in the future.

You would expect that arm64 should have a command like rdmsr 0xc0000082 to read these system registers like ttbr0_el1 but unfortunately I couldn't find one.

Alternatively, another option to show these registers contents would be the rm 0x4f to set the bit mask for the r command... but that although shows a bit more than the regular Integer registers is not the solution either.

example output for r and rm commands:

kd> rm
Register output mask is 4f:
       2 - Integer state (64-bit)
       4 - Floating-point state
       8 - Debug registers
      40 - NEON registers
kd> r
 x0=fffff803ed538aa0   x1=fffff803ed538a30   x2=0000000000000003   x3=fffff803ed538a10
 x4=0000000000000000   x5=fffff803f241c000   x6=ffffd785df80a7f0   x7=0000000000000000
 x8=000000000000d7c3   x9=0000000000011000  x10=0000000000004550  x11=000000000000001f
x12=fffff803f22ad000  x13=0000000000001001  x14=ffffd785df802000  x15=0000000000000600
x16=0000000000000003  x17=fffff803ed538820  x18=fffff803f1bbba34  x19=fffff803ed538aa0
x20=fffff803ec5113c0  x21=fffff803ec5113d0  x22=fffff803f2451d00  x23=0000000000000003
x24=fffff803ed538b20  x25=fffff803f2451000  x26=fffff803ed538b20  x27=fffff803f1800000
x28=0000000000000000   fp=fffff803ed538a20   lr=fffff803f1b373d4   sp=fffff803ed538a20
 pc=fffff803f1a08908  psr=60000044 -ZC- EL1

 d0=    2.13309995079e-313   d1=    8.33242166252e-316
 d2=    6.22223872451e+088   d3=    1.39791210144e-308
 d4=    1.88719426152e+122   d5=    5.12400221257e+102
 d6=    8.33215452122e-316   d7=    6.94122434598e+228
 d8=                     0   d9=                     0
d10=                     0  d11=                     0
d12=                     0  d13=                     0
d14=                     0  d15=                     0
d16=                     0  d17=   -3.19883464952e+307
d18=    1.24348953375e-311  d19=    3.60833840091e-313
d20=                     0  d21=                     0
d22=                     0  d23=                     0
d24=    6.99621747986e+253  d25=   -1.37025872537e+182
d26=    4.46817589305e+076  d27=       0.0184873304943
d28=    7.13506166131e+257  d29=   -6.03392682883e-270
d30=    2.36740574464e+237  d31=    1.80548526765e+125
 q0=0 0 1.4013e-044 7.06966e-031
 q1=2.82689e+023 2.24208e-044 0 6.80798e-033
 q2=3365.96 2.22601e+011 2.39744e+011 49.3168
 q3=845.255 3.36312e-044 9.23136e-040 8.4754e+011
 q4=9.23133e-040 3381.34 3.69912e+015 5.99516e+010
 q5=1.34876e+013 837109 1.33523e+013 3.36312e-044
 q6=7.0696e+028 3.36312e-044 0 6.80401e-033
 q7=3.60554e-042 6.97764e+022 7.49922e+028 1.69282e+022
 q8=0 0 0 0
 q9=0 0 0 0
q10=0 0 0 0
q11=0 0 0 0
q12=0 0 0 0
q13=0 0 0 0
q14=0 0 0 0
q15=0 0 0 0
q16=0 0 0 0
q17=-1.#QNAN -1.94827e+019 -1.#QNAN 0
q18=4.62428e-044 4.2039e-044 8.21161e-043 6.96445e-043
q19=4.2039e-044 1.4013e-045 2.38221e-044 3.0127e-038
q20=0 0 0 0
q21=0 0 0 0
q22=0 0 0 0
q23=0 0 0 0
q24=-1.01884e-031 -2.08158e+029 1.03368e+032 6.35816e+009
q25=-6.85105e-038 9.00862e+021 -1.13638e+023 1.93203e+022
q26=-3.64747 -6.30615e-031 7.27112e+009 -1.8081e-011
q27=-1.47062e-019 -8.19573e-019 1.1479 -0.95345
q28=9.89469e+033 -1.67433e-015 3.14073e+032 1.67504e+022
q29=-1.0893e-025 -6.0525e+022 -4.13779e-034 -3.07939e+023
q30=-2.74816e+025 -1.43784e-006 9.07498e+029 69.093
q31=-5.55539e-013 -6.043e-028 8.4819e+015 0.00020481

kbvr[0] =0000000000000000  kbcr[0] =00000000
kbvr[1] =0000000000000000  kbcr[1] =00000000
kwvr[0] =0000000000000000  kwcr[0] =00000000

What's left to do is to wait for someone to wake up in MSFT in the windbg team and hopefully do something about this, until then we are left only with debug prints and using the MRS opcode (or actually _ReadStatusReg intrinsic) such as this example: reading arm64 system registers

ARM64_SYSREG is a macro defined as:

#define ARM64_SYSREG(op0, op1, crn, crm, op2) \
        ( ((op0 & 1) << 14) | \
          ((op1 & 7) << 11) | \
          ((crn & 15) << 7) | \
          ((crm & 15) << 3) | \
          ((op2 & 7) << 0) )

and in python:

def ARM64_SYSREG(op0, op1, crn, crm, op2):
    return ( ((op0 & 1) << 14) | ((op1 & 7) << 11) | ((crn & 15) << 7) | ((crm & 15) << 3) | ((op2 & 7) << 0) )

ARM64_SYSREG purpose is to encode arguments into a unique constant that represents a system register.

You can find a mapping of all system registers and their arguments for this macro here.

5
  • Thanks. I'm actually writing a WinDbg extension. Do you know if there's any way to retrieve those TTBR registers using IDebug* interfaces?
    – c00000fd
    Commented May 12 at 14:22
  • What is the parameters of the _ReadStatusReg intrinsic? I wonder if I can do the same with IDebugDataSpaces::ReadMsr? It requires "MSR address", and I don't know what it is for those TTBR registers.
    – c00000fd
    Commented May 12 at 14:28
  • Also what is ARM64_SYSREG?
    – c00000fd
    Commented May 12 at 14:36
  • @c00000fd Please see my last edit. Commented May 12 at 17:56
  • Oh, that's a good find. Thanks. I'll check it on Monday.
    – c00000fd
    Commented May 12 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.