1. 程式人生 > >armv8(aarch64)linux核心中flush_dcache_all函式詳細分析

armv8(aarch64)linux核心中flush_dcache_all函式詳細分析


/*

*  Flush the wholeD-cache.

 * Corrupted registers: x0-x7, x9-x11

 */

ENTRY(__flush_dcache_all)

//保證之前的訪存指令的順序

    dsb sy           

      //讀cache level id register

    mrs x0, clidr_el1           // read clidr

      //取bits[26:24](Level of Coherency for the cache hierarchy.)

//需要遵循cache一致性的cache層級(例如有3級cache,但2級需要做一致性)

    and x3, x0, #0x7000000      // extract loc from clidr

      //邏輯右移23位,把bits[26:24]放到bits[2:0]

    lsr x3, x3, #23         // left align loc bit field

      //如果需要做cache一致性的層級為0,則不需要flush,跳轉到finished標記處。

    cbz x3, finished            // if loc is 0, then no need toclean

      //x10存放cache級,從level0 cache開始做flush

      //

以下三個迴圈loop3set/wayx9),

//loop2indexx7),loop1cache level(x10)

    mov x10, #0             // start clean at cache level 0

loop1:

//x10+2後右移一位正好等於1,再加上x10本身正好等於3

      //每執行一次loop1,x2+3*執行次數,目的在於把x0(clidr_el1)右移3位,

//取下一個cache的ctype type fields欄位,clidr_el1的格式見《ARMv8 ARM》

    add x2, x10, x10, lsr #1        /

      //x0邏輯右移x2位,給x1,提取cache型別放到x1中,x0中存放:clidr_el1

    lsr x1, x0, x2         

      //掩掉高位,只取當前cache型別

    and x1, x1, #7 

      /* 判斷當前cache是什麼型別:

* 000  No cache.

* 001  Instruction cache only.

* 010  Data cache only.

* 011  Separate instruction and data caches.

* 100  Unified cache.

*/

      //小於2說明data cache不存在或者只有icache,

//跳轉skip執行,大於等於2繼續執行

    cmp x1, #2             

    b.lt   skip               

/*

 *  Save/disableand restore interrupts.

 * .macro save_and_disable_irqs, olddaif

 * mrs \olddaif,daif                                                                                                                                                      

 * disable_irq

 * .endm

*/

      //儲存daif到x9暫存器中,關閉中斷

    save_and_disable_irqs x9        // make CSSELR and CCSIDR access atomic

      //選擇當前cache級進行操作,csselr_el1暫存器bit[3:1]選擇要操作的cache級

      //第一次執行時x10=0,選擇level 0級cache

      //isb用於同步新的cssr和csidr暫存器

    isb                

      //因為執行了“msr csselr_el1,x10”,所以要重新讀取ccsidr_el1

    mrs x1, ccsidr_el1          // read the new ccsidr

    /*

* .macro  restore_irqs, olddaif                                                                                                                                          

     * msrdaif, \olddaif

    . * endm

        */

    restore_irqs x9

      //x1儲存ccsidr_el1內容,低三位是(Log2(Number of bytes in cache line)) – 4

      //4x2=(Log2(Numberof bytes in cache line))

    and x2, x1, #7          // extract the length of the cachelines

    add x2, x2, #4          // add 4 (line length offset)

    mov x4, #0x3ff

      //邏輯右移3位,提取bits[12:3](Associativityof cache) – 1,

      //x4儲存cacheway

    and x4, x4, x1, lsr #3     // find maximum number on the way size

      //計算x4前面0的個數,存到x5

    clz x5, x4              // find bit position of way sizeincrement

      //提取bits[27:13]位:(Number of sets in cache) - 1

    mov x7, #0x7fff

      //x7中儲存cache中的set

    and x7, x7, x1, lsr #13     // extract max number of the index size

loop2:

      //把x4值備份

    mov x9, x4              // create working copy of max waysize

loop3:

      //把需要操作哪個way儲存到x6

    lsl x6, x9, x5

      //確定操作哪一級的哪個way(x10指定操作哪一級cache)

    orr x11, x10, x6            // factor way and cache number intox11

      //確定操作哪個set

    lsl x6, x7, x2

    orr x11, x11, x6            // factor index number into x11

      //x11中儲存了哪一級cache(10),哪一路cache(x9),哪個set(x7)

    dc  cisw, x11           // clean & invalidate by set/way

      //way數-1

    subs   x9, x9, #1          // decrementthe way

    b.ge   loop3

    subs   x7, x7, #1          // decrementthe index

    b.ge   loop2

skip:

    add x10, x10, #2            // increment cache number,

//為什麼加2不是1?見loop1標號處解釋

    cmp x3, x10

    b.gt   loop1

finished:

    mov x10, #0             // swith back to cache level 0

    msr csselr_el1, x10         // select current cache level incsselr

    dsb sy

    isb

    ret

ENDPROC(__flush_dcache_all)

 如果你對此有疑問,歡迎留言討論。

相關推薦

armv8(aarch64)linux心中flush_dcache_all函式詳細分析

/* *  Flush the wholeD-cache.  * Corrupted registers: x0-x7, x9-x11  */ ENTRY(__flush_dcache_all

linux心中2410_gpio_cfgpin函式分析

2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPIO_OUTPUT) 函式分析:作用設定相應GPIO口的工作模式,輸入、輸出、中斷等。 一,首先巨集展開:為方便描述,展開後用等號表示 #define S3C2410_GPIO

Linux心中trace_xxxx()函式的定義

Linux中trace_xxxx()函式的定義 以trace_netif_receive_skb(skb);為例 該函式的定義: 其中DEFINE_EVENT定義為(include/linux/

Linux心中的bsearch二分查詢函式

/* * bsearch - binary search an array of elements * @key: pointer to item being searched for * @base

linux心中GPIO的使用(二)--標準介面函式

在linux核心中,有一些基本模組可以使用標準的介面函式來操作,比如GPIO、interrupt、clock,所謂的標準介面函式是指一些與硬體平臺無關的、linux下做驅動通用的函式, 常用的有: gpio_request();gpio_free()

linux心中:likely和unlikely函式

  核心原始碼:linux-2.6.38.8.tar.bz2      在Linux核心中likely和unlikely函式有兩種(只能兩者選一)實現方式,它們的實現原理稍有不同,但作用是相同的,下面將結合linux-2.6.38.8版本的核心程式碼來進行講解。    

linux心中的copy_to_user和copy_from_user

Kernel version:2.6.14 CPU architecture:ARM920T Author:ce123(http://blog.csdn.net/ce123) 1.copy_from_user 在學習Linux核心驅動的時候,經常會碰到copy_from_user和c

linux心中的get user和put user

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

淺析linux心中的idr機制

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

【轉】Linux 心中的Device Mapper機制

轉自:https://www.ibm.com/developerworks/cn/linux/l-devmapper/index.html,寫的很通俗易懂,轉載學習下。 Device Mapper 是 Linux2.6 核心中支援邏輯卷管理的通用裝置對映機制,它為實現用於儲存資源管理的塊裝置驅動

linux心中Makefile的使用

linux核心中Makefile 的作用是根據配置的情況,構造出需要編譯的原始檔列表,然後分別編譯,並把目的碼連結到一起,最終形成 Linux 核心二進位制檔案。     由於 Linux 核心原始碼是按照樹形結構組織的,所以 Makefile 也被分佈在

如何開啟linux心中dev_dbg的開關

比如要開啟某個驅動中的dev_dbg,那麼需要在驅動檔案.c中這些行"<linux/device.h>"或者"<linux /platfom_device.h>"(device.h包含platform_device.h)之前定義DEBUG 如: #define DEBUG 1 #

Linux心中的per-cpu變數

per CPU變數 per-CPU變數從字面上即可猜出它大概的含義,這種型別的變數實際上每個CPU都分配了一個該變數的副本。對於per-CPU的訪問幾乎不需要鎖定,因為每個CPU都工作在自己的副本上,另外per CPU變數還可以儲存在CPU自己的快取上,這樣就最大的優化訪問速度和減少

淺談linux心中的I2c驅動(1)

相信瞭解過linux核心的人一定知道在linux核心中有一條非常重要的主線就是匯流排裝置驅動模型。 它是Linux驅動的精髓。不僅在我們今天要講的I2c驅動中存在,像usb,spi,I2s,platform等裝置中也是存在 的。而且在Linux核心的原始碼中,不能把匯流排單

淺談linux心中的I2c驅動(2)

上篇文章將到了I2c驅動的中的i2c-s3c2410.c檔案,它在整個I2c驅動的架構中屬於最底層的。 總結一下它乾的事: A:找到裝置的資源 (通過平臺匯流排裝置驅動模型) B:使用裝置的資源 (硬體的操作) C:註冊裝置       (將裝置掛到I2c匯流排裝置連結串列

Linux心中RAID5原始碼詳解之基本架構與資料結構

Linux核心中RAID5的基本架構與資料結構解析 眾所周知,早年的計算機儲存資料現在磁帶上,然後發展到了磁碟,然而僅僅是單個盤,速度和效能都不是很好,然是,要知道人類的聰明才智是連ET都想不到的,前輩們不斷的猜想,實驗來提高計算機的效能,於是磁碟陣列問世

[經典]Linux心中ioremap對映的透徹理解

  幾乎每一種外設都是通過讀寫裝置上的暫存器來進行的,通常包括控制暫存器、狀態暫存器和資料暫存器三大類,外設的暫存器通常被連續地編址。根據CPU體系結構的不同,CPU對IO埠的編址方式有兩種:  (1)I/O對映方式(I/O-mapped)  典型地,如X86處理器為外設專門

Linux心中的Proc檔案系統(一)

(1)/proc檔案系統的特點和/proc檔案的說明/proc檔案系統是一種特殊的、由軟體建立的檔案系統,核心使用它向外界匯出資訊,/proc系統只存在記憶體當中,而不佔用外存空間。/proc下面的每個

Linux心中ioremap對映的透徹理解 .

幾乎每一種外設都是通過讀寫裝置上的暫存器來進行的,通常包括控制暫存器、狀態暫存器和資料暫存器三大類,外設的暫存器通常被連續地編址。根據CPU體系結構的不同,CPU對IO埠的編址方式有兩種:   (1)I/O對映方式(I/O-mapped)   典型地,如X86處理器為外設專

Linux心中的RCU機制 (詳解)

RCU的設計思想比較明確,通過新老指標替換的方式來實現免鎖方式的共享保護。但是具體到程式碼的層面,理解起來多少還是會有些困難。在《深入Linux裝置驅動程式核心機制》第4章中,已經非常明確地敘述了RCU背後所遵循的規則,這些規則是從一個比較高的視角來看,因為我覺