How to enable MMU ARM1136JFS (ARM v6) for mapping between physical and virtual address space?

I want to enable the data cache. I do not have much experience with ARM, since I am mainly programmed in IA32. I understand that I need to enable MMU to enable the data cache. Since I do not need virtual memory, but I want to enable MMU with individual mapping between the physical and virtual address space for all applications.

Any help / pointers / articles or code is appreciated.

+3
source share
4 answers

Below is the code that allows for mutual mapping between the physical and virtual address space:

#define NUM_PAGE_TABLE_ENTRIES 4096 /* 1 entry per 1MB, so this covers 4G address space */
#define CACHE_DISABLED    0x12
#define SDRAM_START       0x80000000
#define SDRAM_END         0x8fffffff
#define CACHE_WRITEBACK   0x1e

static inline void enable_mmu(void)
{
    static U32 __attribute__((aligned(16384))) page_table[NUM_PAGE_TABLE_ENTRIES];
    int i;
    U32 reg;

    /* Set up an identity-mapping for all 4GB, rw for everyone */
    for (i = 0; i < NUM_PAGE_TABLE_ENTRIES; i++)
        page_table[i] = i << 20 | (3 << 10) | CACHE_DISABLED;
    /* Then, enable cacheable and bufferable for RAM only */
    for (i = SDRAM_START >> 20; i < SDRAM_END >> 20; i++)
    {
        page_table[i] = i << 20 | (3 << 10) | CACHE_WRITEBACK;
    }

    /* Copy the page table address to cp15 */
    asm volatile("mcr p15, 0, %0, c2, c0, 0"
            : : "r" (page_table) : "memory");
    /* Set the access control to all-supervisor */
    asm volatile("mcr p15, 0, %0, c3, c0, 0" : : "r" (~0));

    /* Enable the MMU */
    asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (reg) : : "cc");
    reg|=0x1
    asm volatile("mcr p15, 0, %0, c1, c0, 0" : : "r" (reg) : "cc");
}
+3
source

16 . , " ", () :

/* Setup types for virtual addresses, physical address, and the page table. */
typedef unsigned long vaddr_t;
typedef unsigned long paddr_t;
typedef unsigned long pde_t;

/* Reserve space for a page directory. Must be 16k aligned. */
pde_t page_directory[1 << 12] ALIGNED(1 << 12);

/* Create a 1MB mapping in the given page directory from 'virt' to 'phys'. */
void set_large_page_mapping(pde_t *pd, vaddr_t virt, paddr_t phys)
{
    pde_t entry = 0;
    entry |= phys & 0xfff00000; /* Target of the mapping. */
    entry |= 2;                 /* This is a 1MB section entry. */
    entry |= 1 << 4;            /* Enable caches (C). */
    entry |= 1 << 3;            /* Enable writeback (B). */
    entry |= 3 << 10;           /* Full read/write permission. */
    pd[virt >> 20] = entry;     /* Install the entry. */
}

/* Setup a page directory with one-to-one physical/virtual mappings. */
void setup_one_to_one_mappings(void)
{
    unsigned long i;

    /* Setup a mapping for each 1MB region in the virtual address space. */
    for (i = 0; i < (1 << 12); i++) {
       /* Map the virtual address "i << 20" to phys address "i << 20". */
       set_large_page_mapping(page_directory, i << 20, i << 20);
    }

    /* TODO: Write function to install this page directory and enable the MMU. */
    enable_mmu(page_directory);
}

enable_mmu , :

  • ;
  • TLB;
  • ( , ..);
  • TTBR0, PD, ;
  • MMU.

, () (, , , Linux FreeBSD). , , , , .

+3

- (. ). , . . trm mmu / , mmu.

arm11 mpcore, , , , , mmu arm9. mpcore , 16 , , , 16 mmu.

mmu , , , , mmu, - . ( ). , .

, , , , mmu , , , , .

mmu, , , , mmu. . , . .

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MMUTABLEBASE 0x00000000

#define MMUALLOC (0x8000>>2)

unsigned int mmu_table[MMUALLOC];
unsigned int mmu_table_owner[MMUALLOC];

#define TOP_LEVEL_WORDS (1<<((31-20)+1))
#define COARSE_TABLE_WORDS (1<<((19-12)+1))
#define SMALL_TABLE_WORDS (1<<((11-0)+1))

unsigned int base;
unsigned int nextfree;


unsigned int next_coarse_offset ( unsigned int x )
{
    unsigned int mask;

    mask=(~0)<<(10-2);
    mask=~mask;
    while(x&mask) x++; //lazy brute force
    return(x);
}

unsigned int add_one ( unsigned int add, unsigned int flags )
{
    unsigned int ra;
    unsigned int rb;
    unsigned int rc;

    ra=add>>20;
    if(mmu_table[ra])
    {
        printf("Address %08X already allocated\n",add);
        return(1);
    }
    add=ra<<20;

    rb=next_coarse_offset(nextfree);
    rc=rb+COARSE_TABLE_WORDS;

    if(rc>=MMUALLOC)
    {
        printf("Not enough room\n");
        return(1);
    }
    nextfree=rc;

    mmu_table[ra]=(MMUTABLEBASE+(rb<<2))|0x00000001;

    for(ra=0;ra<COARSE_TABLE_WORDS;ra++)
    {
        mmu_table[rb+ra]=(add+(ra<<12))|0x00000032|flags;
        mmu_table_owner[rb+ra]=(add+(ra<<12));
    }
    return(0);
}



int main ( void )
{

    memset(mmu_table,0xF0,sizeof(mmu_table));

    for(nextfree=0;nextfree<TOP_LEVEL_WORDS;nextfree++)
    {
        mmu_table[nextfree]=0x00000000;
        mmu_table_owner[nextfree]=nextfree<<20;
    }

    if(add_one(0xD6000000,0x0000|8|4)) return(1);
    if(add_one(0x00000000,0x0000|8|4)) return(1);
    if(add_one(0xC3F00000,0x0000)) return(1);
    if(add_one(0xCA000000,0x0000)) return(1);


    printf("    .globl _start\n");
    printf("_start:\n");

    for(base=0;base<nextfree;base++)
    {
        printf(".word 0x%08X ;@ [0x%08X] 0x%08X\n",mmu_table[base],MMUTABLEBASE+(base<<2),mmu_table_owner[base]);
    }

    for(;base<MMUALLOC;base++)
    {
        printf(".word 0x00000000 ;@ [0x%08X]\n",MMUTABLEBASE+(base<<2));
    }
    printf("   b   zreset\n");
    for(base=0;base<15;base++) printf("    b zhang\n");
    printf("zhang: b zhang\n");
    printf("zreset:\n");
    printf("  ldr pc,=reset\n");
    printf("\n");


    return(0);
}
+2

, , MMU ( , MMU):

    void enable_data_cache()
    {
        asm volatile( "  mrc p15, 0, r0, c1, c0, 0" );  // Read c1 into r0
        asm volatile( "  orr r0, r0, #4" );             // Set bit 2: Dcache
        asm volatile( "  mcr p15, 0, r0, c1, c0, 0" );  // Return r0 to c1
    }

    void disable_data_cache()
    {
        asm volatile( "_disable_data_cache_start_:" );
        asm volatile( "  mrc p15, 0, r15, c7, c14, 3" ); // test, clean and invalidate
        asm volatile( "  bne _disable_data_cache_start_" );

        asm volatile( "  mov r0,#0" );
        asm volatile( "  mcr p15, 0, r0, c7, c5, 0" ); //  invalidate I cache
        asm volatile( "  mcr p15, 0, r0, c7, c10, 4"); //  drain write buffer

        asm volatile( "  mrc p15, 0, r0, c1, c0, 0" );  // Read c1 into r0
        asm volatile( "  bic r0, r0, #4"     );         // Clear bit 2: disable Dcache
        asm volatile( "  mcr p15, 0, r0, c1, c0, 0"  ); // Return r0 to c1
    }

    void clean_data_cache()
    {
        asm volatile( "_clean_data_cache_start_:" );
        asm volatile( "  mrc p15, 0, r15, c7, c14, 3" ); // test, clean and invalidate
        asm volatile( "  bne _clean_data_cache_start_" );
    }

    void enable_instruction_cache()
    {
        asm volatile( "  mrc p15, 0, r0, c1, c0, 0" );  // Read c1 into r0
        asm volatile( "  orr r0, r0, #4096" );          // Set bit 12: Icache
        asm volatile( "  mcr p15, 0, r0, c1, c0, 0" );  // Return r0 to c1
    }

    void disable_instruction_cache()
    {
        asm volatile( "  mrc p15, 0, r0, c1, c0, 0" );  // Read c1 into r0
        asm volatile( "  bic r0, r0, #4096" );          // Clearr bit 12: Icache
        asm volatile( "  mcr p15, 0, r0, c1, c0, 0" );  // Return r0 to c1
    }
0

Source: https://habr.com/ru/post/1758714/


All Articles