ARMv8 Linux kernel source code analysis: __flush_dcache_all()

Publisher:qiuxubiaoLatest update time:2020-01-19 Source: eefocusKeywords:ARMv8 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

1.1 

/*


 *  __flush_dcache_all()


*  Flush the wholeD-cache.


 * Corrupted registers: x0-x7, x9-x11


 */


ENTRY(__flush_dcache_all)


// Ensure the order of previous memory access instructions


    etc           


      //读cache level id register


    mrs x0, clidr_el1           // read clidr


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


//The cache hierarchy that needs to follow cache consistency (for example, there are 3 levels of cache, but level 2 needs to be consistent)


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


      //Logical right shift 23 bits, put bits[26:24] into bits[2:0]


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


      //If the cache consistency level needs to be 0, no flush is required and jump to the finished mark.


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


      //x10 stores the cache level, flushing starts from level 0 cache


      //The following three loops loop3 is set/way (x9),


//loop2 is index (x7), loop1 is cachelevel (x10)


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


loop1:


//x10+2 shifted right by one position equals 1, plus x10 itself equals 3


      //Each time loop1 is executed, x2+3*number of executions, the purpose is to shift x0 (clidr_el1) right by 3 bits,


//Get the ctype type fields of a cache. For the format of clidr_el1, see "ARMv8 ARM"


    add x2, x10, x10, lsr #1        /


      //x0 is logically shifted right by x2 bits, given to x1, the cache type is extracted and placed in x1, and x0 is stored in: clidr_el1


    lsr x1, x0, x2         


      //Mask off the high bit and only take the current cache type


    and x1, x1, #7 


      /* Determine what type of cache is currently:


* 000  No cache.


* 001  Instruction cache only.


* 010  Data cache only.


* 011  Separate instruction and data caches.


* 100  Unified cache.


*/


      //Less than 2 means data cache does not exist or there is only icache,


// Skip execution, continue execution if value is greater than or equal to 2


    cmp x1, #2             


    b.lt   skip               


/*


 * Save/disable and restore interrupts.


 * .macro save_and_disable_irqs, olddaif


 * mrs olddaif,daif                                                                                                                                                      

 * disable_irq


 * .endm


*/


      //Save daif to x9 register and disable interrupt


    save_and_disable_irqs x9        // make CSSELR and CCSIDR access atomic


      //Select the current cache level to operate, csselr_el1 register bit [3:1] selects the cache level to operate


      //When executing for the first time, x10=0, select level 0 cache


    msr csselr_el1,x10        


      //isb is used to synchronize the new cssr and csidr registers


    isb                


      //Because "msr csselr_el1,x10" is executed, ccsidr_el1 should be re-read


    mrs x1, ccsidr_el1          // read the new ccsidr


    /*


* .macro  restore_irqs, olddaif                                                                                                                                          


     * msr daif, old daif


    . * endm


        */


    restore_irqs x9


      //x1 stores the contents of ccsidr_el1, the lower three bits are (Log2(Number of bytes in cache line)) – 4


      //加4后x2=(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)


    move x4, #0x3ff


      //Logical right shift 3 bits, extract bits[12:3](Associativity of cache) – 1,


      //x4 stores the number of ways in the cache


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


      // Calculate the number of 0s before x4 and store it in x5


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


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


    move x7, #0x7fff


      //x7 stores the number of sets in the cache


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


loop2:


      //Back up the x4 value


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


loop3:


      //Store the way to be operated in x6


    lsl x6, x9, x5


      //Determine which level of way to operate (x10 specifies which level of cache to operate)


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


      //Determine which set to operate


    lsl x6, x7, x2


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


      // Which level of cache (10), which way of cache (x9), which set (x7) is stored in x11


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


      //Number of ways - 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,


//Why is adding 2 not 1? See the explanation at the loop1 label


    cmp x3, x10


    b.gt walk1


finished:


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


    msr csselr_el1, x10         // select current cache level incsselr


    etc


    isb


    right


ENDPROC(__flush_dcache_all)

Keywords:ARMv8 Reference address:ARMv8 Linux kernel source code analysis: __flush_dcache_all()

Previous article:Classification, format and usage of branch instructions in ARMv8
Next article:Analysis of ARMv8 Linux kernel exception handling process

Recommended ReadingLatest update time:2024-11-16 12:49

Arm Linux kernel startup start_kernel
After understanding the assembly before kernel startup, let's take a look at the formal C language startup code, that is, our start_kernel function. start_kernel is quite large, and each function called in it is enough to give us a headache. I will only briefly describe the functions here, so that we can have a more in
[Microcontroller]
ARMv7: Linux Kernel Boot
1. If the kernel image is compressed, it needs to be decompressed. The first step of booting is to start from decompression: archarmbootcompressedhead.S 2. After decompression, the kernel image already exists in ARM. Let's start running. The kernel starts running from /arch/arm/kernel/head.S. The entry code is: 1
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号