assemblymemory-managementtlbmicroblaze

Accessing MMU/TLB at boot on Microblaze


I am seeking to set up the TLB on a Microblaze (actually simulated on OVP), and have C_USE_MMU set to 3.

This is my boot code:

    .global _start
    .section .vectors.reset, "ax"
    .align 2
    .ent _start
    .type _start, @function

_start:
    brai    _actualstart
    .end _start

....

    .section .text
    .global _actualstart
    .align 4
    .ent _actualstart
    .type _actualstart, @function

 _actualstart:
    mfs r1, rmsr
    nop
    ori r1, r1, 0x00040000
    mts rmsr, r1
    nop

    addik   r3, r0, 0x3F    /* Microblaze TLB has 64 entries */
_zeroouttlb:
    mts rtlbx, r3
    mts rtlbhi, r0
    mts rtlblo, r0
    bgtid   r3, _zeroouttlb /* Uses delay slot */
    addik   r3, r3, -1

The line below updates r1 to 0x00040000 as you would expect:

ori r1, r1, 0x00040000

But on the next line:

mts rmsr, r1

The value of msr is left unchanged and so the code goes on to fail on:

mts rtlbhi, r0

With:

Fatal (MB_TLB) Attempting Write to TLBHI when no MMU available

(As msr has not been updated it still reads 0x00000000 so the processor is correct in assessing there is no MMU support available).

Why won't my code update the msr?


Solution

  • The problem is that you're setting wrong bit. Many reference guides describing BigEndian architecture assume that bit #31 is 2^0 and bit #0 is 2^31. MicroBlaze manual is one of those using this confusing notation.

    In your case if you want to set bit VM (BigEndian bit 18) you need to set msr to 0x00002000 or 1 << (31-18).

    So basically changing line:

    ori r1, r1, 0x00002000
    mts rmsr, r1
    nop
    

    should make everything work.