在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > arm linux 從入口到start_kernel 代碼分析 - 6

            arm linux 從入口到start_kernel 代碼分析 - 6

            作者: 時間:2016-11-10 來源:網絡 收藏
            5. 開啟mmu

            開啟mmu是又函數 __enable_mmu 實現的.

            在進入 __enable_mmu 的時候, r0中已經存放了控制寄存器c1的一些配置(在上一步中進行的設置), 但是并沒有真正的打開mmu,
            在 __enable_mmu 中,我們將打開mmu.

            此時,一些特定寄存器的值如下所示:
            r0 = c1 parameters (用來配置控制寄存器的參數)
            r4 = pgtbl (page table 的物理基地址)
            r8 = machine info (struct machine_desc的基地址)
            r9 = cpu id (通過cp15協(xié)處理器獲得的cpu id)
            r10 = procinfo (struct proc_info_list的基地址)

            在 arch/arm/kernel/head.S 中:

            本文引用地址:http://www.biyoush.com/article/201611/317208.htm

            00146: .type__enable_mmu, %function
            00147: __enable_mmu:
            00148: #ifdef CONFIG_ALIGNMENT_TRAP
            00149: orrr0, r0, #CR_A
            00150: #else
            00151: bicr0, r0, #CR_A
            00152: #endif
            00153: #ifdef CONFIG_CPU_DCACHE_DISABLE
            00154: bicr0, r0, #CR_C
            00155: #endif
            00156: #ifdef CONFIG_CPU_BPREDICT_DISABLE
            00157: bicr0, r0, #CR_Z
            00158: #endif
            00159: #ifdef CONFIG_CPU_ICACHE_DISABLE
            00160: bicr0, r0, #CR_I
            00161: #endif
            00162: movr5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) |
            00163: domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |
            00164: domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) |
            00165: domain_val(DOMAIN_IO, DOMAIN_CLIENT))
            00166: mcrp15, 0, r5, c3, c0, 0@ load domain access register
            00167: mcrp15, 0, r4, c2, c0, 0@ load page table pointer
            00168: b__turn_mmu_on
            00169:
            00170:
            00181: .align5
            00182: .type__turn_mmu_on, %function
            00183: __turn_mmu_on:
            00184: movr0, r0
            00185: mcrp15, 0, r0, c1, c0, 0@ write control reg
            00186: mrcp15, 0, r3, c0, c0, 0@ read id reg
            00187: movr3, r3
            00188: movr3, r3
            00189: movpc, r13

            第146, 147行: 函數聲明
            第148 - 161行: 根據相應的配置,設置r0中的相應的Bit. (r0 將用來配置控制寄存器c1)
            第162 - 165行: 設置 domain 參數r5.(r5 將用來配置domain)
            第166行: 配置 domain (詳細信息清參考arm相關手冊)
            第167行: 配置頁表在存儲器中的位置(set ttb).這里頁表的基地址是r4, 通過寫cp15的c2寄存器來設置頁表基地址.

            第168行: 跳轉到 __turn_mmu_on. 從名稱我們可以猜到,下面是要真正打開mmu了.
            (繼續(xù)向下看,我們會發(fā)現,__turn_mmu_on就下當前代碼的下方,為什么要跳轉一下呢? 這是有原因的. go on)
            第169 - 180行: 空行和注釋. 這里的注釋我們可以看到, r0是cp15控制寄存器的內容, r13存儲了完成后需要跳轉的虛擬地址(因為完成后mmu已經打開了,都是虛擬地址了).

            第181行: .algin 5 這句是cache line對齊. 我們可以看到下面一行就是 __turn_mmu_on, 之所以
            第182 - 183行: __turn_mmu_on 的函數聲明. 這里我們可以看到, __turn_mmu_on 是緊接著上面第168行的跳轉指令的,只是中間在第181行多了一個cache line對齊.
            這么做的原因是: 下面我們要進行真正的打開mmu操作了, 我們要把打開mmu的操作放到一個單獨的cache line上. 而在之前的"啟動條件"一節(jié)我們說了,I Cache是可以打開也可以關閉的,這里這么做的原因是要保證在I Cache打開的時候,打開mmu的操作也能正常執(zhí)行.
            第184行: 這是一個空操作,相當于nop. 在arm中,nop操作經常用指令 mov rd, rd 來實現.
            注意: 為什么這里要有一個nop,我思考了很長時間,這里是我的猜測,可能不是正確的:
            因為之前設置了頁表基地址(set ttb),到下一行(185行)打開mmu操作,中間的指令序列是這樣的:
            set ttb(第167行)
            branch(第168行)
            nop(第184行)
            enable mmu(第185行)
            對于arm的五級流水線: fetch - decode - execute - memory - write

            他們執(zhí)行的情況如下圖所示:

            +------------+---+---+---+---+---+---+---+---+
            | set ttb | F | D | E | M | W | | | |
            +------------+---+---+---+---+---+---+---+---+
            | branch | | F | D | E | | | | |
            +------------+---+---+---+---+---+---+---+---+
            | nop | | | | | F | D | | |
            +------------+---+---+---+---+---+---+---+---+
            | enable mmu | | | | | | F | | |
            +------------+---+---+---+---+---+---+---+---+


            F - fetch
            D - Decode
            E - Execute
            M - Memory
            W - Write Register

            這里需要說明的是,branch操作會在3個cycle中完成,并且會導致重新取指.

            從這個圖我們可以看出來,在enable mmu操作取指的時候, set ttb操作剛好完成.


            第185行: 寫cp15的控制寄存器c1, 這里是打開mmu的操作,同時會打開cache等(根據r0相應的配置)
            第186行: 讀取id寄存器.
            第187 - 188行: 兩個nop.
            第189行: 取r13到pc中,我們前面已經看到了, r13中存儲的是 __switch_data (在 arch/arm/kernel/head.S 91行),下面會跳到 __switch_data.

            第187,188行的兩個nop是非常重要的,因為在185行打開mmu操作之后,要等到3個cycle之后才會生效,這和arm的流水線有關系.
            因而,在打開mmu操作之后的加了兩個nop操作.



            評論


            技術專區(qū)

            關閉