ARM架构 --- MMU的初始化

上一张里忘说的一个理论,TLB,快表
TLB (Translation Lookaside Buffers)即转换快表,又简称快表,可以理解为MMU内部专用的存放页表的cache,保存着最近使用的PTE乃至全部页表。MMU接收到虚拟地址后,首先在TLB中查找,如果找到该VA对应的PTE就直接转换,找不到再去外存页表查找,并置换进TLB。TLB属于片上SRAM,访问速度快,通过TLB缓存PTE可以节省MMU访问外存页表的时间,从而加速虚实地址转换。TLB和CPU cache的工作原理一样,只是TLB专用于为MMU缓存页表。

在系统上电,初始化MMU时,TLB是需要清空的,ARM920T需要配置CP15协处理器的 C10寄存器

先来回顾 如何通过程序给出的一个虚拟地址找到对应的物理地址的:
在这里插入图片描述
初始化MMU其实就是在为这个过程做填充准备

1 生成PTE 也就是页表项

对物理地址的后20位清零
设定段页大小为1M

2 将生成的PTE放到指定物理地址上

地址页表基地址baddr
保证页表基地址mask到该地址所在的段地址上 baddr&0xffffc000
页表项PTE的偏移是虚拟地址的前12位再<<2 也就是占用14位
所以第二步要与上0xffffc000 清零后14位


初始化MMU的步骤:

  1. find a available memory zone to store TTB
    (ARM920T mmu requires the page table stored 16KB aligned)
  2. fill map relation in the page table
  3. write base address of the page table to cp15-c2 register
  4. disable tlb and cache
  5. enable mmu(mmu ctrl register is cp15-c1)
#include "../include/hylicos_types.h"
#include "../include/hylicos_headctrl.h"

void init_platform()
{
    s3c2440mmu_init();          //init s3c2440 mmu
    s3c2440vector_init();       //init s3c2440 interrupt vectors

    return;
}

#ifdef CFG_S3C2440A_PLATFORM
LKHEAD_T void s3c2440mmu_init()
{
    /*
     * 1. find a available memory zone to store TTB
     *    (ARM920T mmu requires the page table stored 16KB aligned)
     * 2. fill map relation in the page table
     * 3. write base address of the page table to cp15-c2 register
     * 4. enable mmu(mmu ctrl register is cp15-c1)
    */
    uint_t paddr = 0;
    u32_t  pte_desc= 0;
    /* 1. 0x3000_4000 cause physical address from 0x3000_0000 to 0x33ff_ffff */
    u32_t* pgd_baseaddr= (u32_t* )PAGE_TLB_DIR;        

    /* 2. simply use biggest page-->1MB since page table has 4096 PTE*/
    for(uint_t i=0; i<PAGE_TLB_SIZE; i++)
    {
        pte_desc = paddr | PTE_SECT_AP | PTE_SECT_NOCW | PTE_SECT_BIT | PTE_SECT_DOMAIN; //made a pte descriptor
        pgd_baseaddr[i] = pte_desc;     //index i 
        paddr += 0x100000;     // 1MB
    }
    pgd_baseaddr[0] = SDRAM_MAPVECTPHY_ADDR | PTE_SECT_AP | PTE_SECT_DOMAIN | PTE_SECT_NOCW | PTE_SECT_BIT;
    /* pdg has been built. let's do step 3 */
    s3c2440mmu_save_pgd(pgd_baseaddr);
    /* mask cache and tlb before enable mmu */
    s3c2440mmu_mask_cache();
    /* set domain to control visit privilege */
    s3c2440mmu_set_domain(~0);
    /* step 4: enable mmu */
    s3c2440mmu_enable();

    return ;

}
LKHEAD_T void s3c2440mmu_save_pgd(u32_t pgd_baseaddr)
{
    __asm__ __volatile__(
        /* write pgd to cp15 c2 reg */
        "mcr p15,0,%[pgdreg],c2,c0,\n\t"
        :
        /* attribute a general register to store pdg_baseaddr value */
        : [pgdreg] "r" (pgd_baseaddr)
        : "cc", "memory"
    );
    return;
}

LKHEAD_T void s3c2440mmu_set_domain(u32_t domain)
{
    __asm__ __volatile__(
        /* config cp15 c3reg to set domain with 0xffff */
          "mcr p15,0,%[domainval],c3,c0,0 \n\t"
        :
        : [domainval] "r" (domain)
        : "cc", "memory" 
    );
    return;
}

LKHEAD_T void s3c2440mmu_mask_cache()
{
    __asm__ __volatile__(
          "mov r0,#0 \r\t"
          "mcr p15, 0, r0, c7, c7, 0 \n\t"    //disable data cache and cmd cache
          "mcr p15, 0, r0, c7, c10, 4 \n\t"   //clear write cache
          "mcr p15, 0, r0, c8, c7, 0 \n\t"    //disable data tlb and cmd tlb
        :
        :
        : "cc", "memory", "r0"  
    );
    return;
}

LKHEAD_T void s3c2440mmu_enable()
{
        __asm__ __volatile__(
        "mrc p15,0,r0,c1,c0,0 \n\t"
        "orr r0 ,#1 \n\t"
        "mcr p15,0,r0,c1,c0,0 \n\t"
        "nop \n\t"
        "nop \n\t"
        "nop \n\t"
        "nop \n\t"
        "nop \n\t"
        "nop \n\t"
        "nop \n\t"
        :
        :
        : "r0","cc","memory"
        
    );
    return;
}

LKHEAD_T void s3c2440vector_init()
{
    s3c2440vector_copy();
    return;
}

LKHEAD_T void s3c2440vector_copy()
{
    u32_t* src_end = (u32_t* )(&__end_hylic_hal_vector);//linker define and will be substitud with a virtual address
    u32_t* src_pos = (u32_t* )(&vector);                //vector(virtual)                 src <--> unkown(physical)
    u32_t* dst     = (u32_t* )(CPU_VECTOR_VIRADR);      //CPU_VECTOR_VIRADR(virtual 0) target <--> 0x3000_0000  

    for(uint_t i=0; i<4096; i++)                        //clear 0 from 0(virtual) / 0x3000_0000(physical) to x+4096
    {
        dst[i] = 0;         
    }

    for( ;src_pos < src_end; src_pos++,dst++)           //copy vector table from vector(virtual)
    {
        *dst = *src_pos;
    }
    return;
}

#endif /* End Of  CFG_S3C2440A_PLATFORM */
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值