1 Working Principle of ARM920T MMU
Displays the MMU address conversion relationship.
Address of the first-level table item (PMD) = (TLB) & (0xffffc000) + (Table index) <2 );
Note 1: TLB (translate Table Base), that is, the base address of the conversion table.
NOTE 2: because each table item occupies 32 bits (4 bytes), (Table index) <2
Content of the first-level table item (* PMD) = (PTE) & (0xfffffc00) + prot_l1;
Bytes -------------------------------------------------------------------------------------
The address (PTE) = (PTE) & (0xfffffc00) + (L2 table index) <2) of the second-level table item );
Content (* PTE) = (PA) & (0xfffff000) + prot_pte;
2 create_mapping Analysis
// Use this function to create static memory ing for physical addresses
Static void _ init create_mapping (struct map_desc * MD)
{
...
PGD = pgd_offset_k (ADDR );
// Calculate the PGD address (64 bits) = (mm)-> PGD + pgd_index (ADDR ))
// = (Mm)-> PGD + (ADDR)> 21 ))
// PMD address (32 bits) = (mm)-> PGD + (ADDR)> 20 ))
End = ADDR + length;
// Pgdir_size = (1ul <pgdir_shift) = 2 m
// Process two consecutive first-level table items at a time: 2*1 m = 2 m
Do {
Unsigned long next = pgd_addr_end (ADDR, end );
Alloc_init_section (PGD, ADDR, next, Phys, type );
Phys + = Next-ADDR;
ADDR = next;
} While (PGD ++, ADDR! = END );
}
// Try to use field ing
Static void _ init alloc_init_section (pgd_t * PGD, unsigned long ADDR,
Unsigned long end, unsigned long phys,
Const struct mem_type * type)
{
Pmd_t * PMD = pmd_offset (PGD, ADDR); // level-1 Table pointer
// PMD address (32 bits) = (mm)-> PGD + (ADDR)> 20 ))
/* Use field ing when the size is 1 MB aligned with the address */
If (ADDR | End | phys )&~ Section_mask) = 0 ){
Pmd_t * P = PMD;
If (ADDR & section_size)
PMD ++;
Do {
* PMD = _ PMD (Phys | type-> prot_sect );
Phys + = section_size;
} While (PMD ++, ADDR + = section_size, ADDR! = END );
// 2 MB, 2 cycles
Flush_pmd_entry (P );
} Else {
/* To use small page ing, the second-level table must be allocated 4 kb (1 page )*/
Alloc_init_pte (PMD, ADDR, end, _ phys_to_pfn (Phys), type );
}
}
// Small page ing
Static void _ init alloc_init_pte (pmd_t * PMD, unsigned long ADDR,
Unsigned long end, unsigned long PFN,
Const struct mem_type * type)
{
Pte_t * PTE; // List table pointer
// When the content of the first-level table item is empty, allocate space for the second-level table Item 2*512*4 = 4kb (1 page)
If (pmd_none (* PMD )){
PTE = alloc_bootmem_low_pages (2 * ptrs_per_pte * sizeof (pte_t ));
_ Pmd_populate (PMD, _ Pa (PTE) | type-> prot_l1 );
// Assign a value to the first-level table item. The value of PMD is a pointer and points to the address to be assigned.
// Pmdp [0] = _ PMD (pmdval );
// Pmdp [1] = _ PMD (pmdval + 256 * sizeof (pte_t ));
}
PTE = pte_offset_kernel (PMD, ADDR );
Do {
Set_pte_ext (PTE, pfn_pte (PFN, _ pgprot (Type-> prot_pte), 0 );
PFN ++;
} While (PTE ++, ADDR + = page_size, ADDR! = END );
// 2 MB, 2 MB/4 kb = 512 times (max)
}
. Macro armv3_set_pte_ext wc_disable = 1
STR R1, [R0], #-2048 @ H/W pte0/1 in Linux version MMU
EOR R3, R1, # l_pte_present | l_pte_young | l_pte_write | l_pte_dirty
Bic R2, R1, # pte_small_ap_mask @ keep C, B bits
Bic R2, R2, # pte_type_mask
ORR R2, R2, # pte_type_small
Tst R3, # l_pte_user @ user?
Orrne R2, R2, # pte_small_ap_uro_srw
Tst R3, # l_pte_write | l_pte_dirty @ write and dirty?
Orreq R2, R2, # pte_small_ap_uno_srw
Tst R3, # l_pte_present | l_pte_young @ present and young?
Movne R2, #0
. If/wc_disable
# Ifdef config_cpu_dcache_writethrough
Tst R2, # pte_cacheable
Bicne R2, R2, # pte_bufferable
# Endif
. Endif
STR R2, [R0] @ hardware version
. Endm
3 Linux MMU
4 9260ek memory ing
This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/huyugv_830913/archive/2010/09/14/5884628.aspx