Arm: Disabling Mmu and Updating Pc

ARM: Disabling MMU and updating PC

Since both Jacen and dwelch kindly brought the answer I needed through a comment (each), I will answer my own question here for the sake of clarity:

The trick was simply to add an identity mapping from/to the page doing the transition, allowing us to jump to it with a "physical" (though actually virtual) PC, then disable MMU.

Here is the final code (a bit specific, but commented):

    /* Duplicate mapping to here */

mrc p15, 0, r4, c2, c0, 0 // Get TTRB0
ldr r10, =0x00003fff
bic r4, r10 // Extract page table physical base address
orr r4, #0xc0000000 // Nastily "translate" it to the virtual one

/*
* Here r8 holds vf_suspend's physical address. I had no way of
* doing this more "locally", since both physical and virtual
* space for my code are runtime-allocated.
*/

add lr, r8, #(phys_block-vf_suspend) // -> phys_block physical address

lsr r9, lr, #20 // SECTION_SHIFT -> Page index
add r7, r4, r9, lsl #2 // PMD_ORDER -> Entry address
ldr r10, =0x00000c0e // Flags
orr r9, r10, r9, lsl #20 // SECTION_SHIFT -> Entry value
str r9, [r7] // Write entry

ret lr // Jump / transition to virtual addressing

phys_block:
/* disable the MMU and TEX */
isb
mrc p15, 0, r6, c1, c0, 0
ldr r7, =0x10000001
bic r6, r6, r7
mcr p15, 0, r6, c1, c0, 0 @ turn on MMU, I-cache, etc
mrc p15, 0, r6, c0, c0, 0 @ read id reg
isb
dsb
dmb

/* disable the Icache, Dcache and branch prediction */
mrc p15, 0, r6, c1, c0, 0
ldr r7, =0x1804
bic r6, r6, r7
mcr p15, 0, r6, c1, c0, 0
isb

// Done !

Problems enabling MMU on ARM Cortex-A

The translation table has to be aligned on a 16k boundary. Try 0x14000 or 0x18000.

Domain in arm architecture means what

TL;DR The DACR not only decreases the context switch code path, but can also speed execution after the context switch occurs.


There are several links which explain the specifics of Domain Access Control Register or DACR. For example ARM's Memory access permissions and domains. However, this page and many others don't explain why you might need this feature; especially for people use to embedded applications.

A prior ARM feature (ARM architecture V5) was the PID. The reason for this feature is the same as the DACR and domains. What is an MMU used for?

  • Privilege separation - or giving some entities (task, thread, etc) access to memory and other limited (read-only) or none.
  • Memory remapping - a virtual to physical translation allows sparse/separated memory to become continuous.
  • Paging - a fault handler can swap in/out memory on access by less privileged code.
  • Access behaviour - the MMU can specify whether memory is cacheable, read/write, should be buffered, etc.

The DACR (and PID) are only concerned with the first (Privilege separation). On a context switch an OS must manage this separation. With most MMUs (historically on the ARM), there are only two privileges being user and super. In order to accommodate multiple tasks, the super MMU code must alter the MMU table. This is complex as the ARM has a TLB and cache, both of which have virtual addresses and depend on the MMU table.

The DACR (and PID) allow the MMU mappings to change with a single register write. Moreover, the TLB and cache also have domain information (and modified address for PID). This means these entries do not need to be flushed (and repopulated) on a context switch. The domains are advantageous to the PID as multiple access profiles can exist. For instance, shared library code may remain accessible on a context switch while the main task/thread binary is switched out.

Compare work with the DACR versus updating the MMU tables.

  1. Change at least the L1 page tables to map correct profile.
  2. clean/invalidate the L1 table and others in page table update (see below).
  3. invalidate the TLB entries (most likely the whole thing for simplicity).
  4. invalidate the cache entries in MMU table; probably the whole thing again.

This is versus changing a single register. Moreover, you will probably invalidate the entire cache and TLB. With the DACR and a brief context switch, code/data can remain in the cache and MMU page table entries in the TLB. For example, a system with a check email task and a movie player.

The decoding of audio/video is highly CPU and memory intensive. Occasionally, the email client will poll a network server for information. Usually there is nothing. During this brief transition only a small (1-4k) of check email code may be needed; a single TLB entry. Cache is typically 32k+, so much of the audio/video cache and TLB entries can remain valid.

So the DACR not only decreases the context switch code path, but can also speed execution after the context switch occurs.

Possible to set the ARM MMU to allow code execution, but not allow reading

It would seem the answer is no.

From ARM® Architecture Reference Manual ARMv7-A and ARMv7-R edition section B3.7.2

A processor can
execute instructions from a memory region only if the access permissions for its current state permit read access, and the XN bit is set to 0.



Related Topics



Leave a reply



Submit