Question

So, basically, I want to enable the memory management unit on an ARMv7 core. The actual procedure is pretty much trivial. I just need to load the address of the translation table into TTBR0 and enable the MMU using the control register.

/* enable mmu */
mcr p15, 0, r0, c2, c0, 0
mrc p15, 0, r12, c1, c0, 0
orr r12, r12, #0x1
mcr p15, 0, r12, c1, c0, 0

Now, the problem arises as soon as the MMU is enabled, because on ARMv7 (unlike on some other versions of the ARM architecture), the CPU begins fetching from the virtual address immediately. So, if the bootloader is running at 0x10000000 and then enables the MMU, unless it enters an identity mapping first, the next fetch at 0x10000004 will cause a prefetch abort. Now, I'm aware that it's possible to do this using an identity mapping during the initial enabling of the MMU. However, the same problem will also occur when switching translation tables (loading new values into TTBR0).

So, essentially, I'm looking for a more or less straightforward way of loading a new value into TTBR0 (or just turning the MMU on) and then, immediately jumping to a new address, which will be valid in the new map. This was possible on earlier architectures because at least 4 instructions following the instruction that enabled the MMU or changed the state were fetched from the old address. Ideally, I want to be able to do that without relying on incredibly ugly hacks where you have to create an identity mapping every time you want to switch page tables or turn the MMU on.

To clarify what I meant when I was talking about older architectures, here is a link to the ARM infocenter page explaining how to turn on the MMU on ARM720T: 7.16.1. Enabling the MMU

Était-ce utile?

La solution

The short answer is that there is no way of doing exactly what you ask in ARMv7-A. The ARM720T example was an extremely microarchitecture-specific hack and could never have been guaranteed to be portable between different processors.

For ARMv7-A There is no portable way of not using an identity mapping for turning MMU on/off, but as for updating translation tables: What you can do (which was not available in ARM720T) is to use the combination of TTBR1/TTBR0 to hold your descriptors. The N field in TTBCR configures the size of the TTBR0 table overlaying the TTBR1 one. This way, as long as your TTB switching code resides in a region described through a different TTBR than the one you are updating, there is no conflict of maps.

The other option would be to rewrite the translation tables described by TTBR0 rather than switching.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top