Friday, May 6, 2011

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

Sometime ago I wanted to enable L2 cache on an ARM1136-JFS based processor. The problem with this ARM core is that you cant enable L2 cache without enabling MMU and enabling MMU means to have a physical to virtual address mapping. But I didnt need any virtual memory and only wanted to enable L2 cache. The only way that I could think of was to create a one-to-one physical-to-virtual address mapping so that I could use L2 cache. The code that I wrote, after reading uboots source code, is given below.

/* 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);
}

 

No comments: