捉虫日记 0001: Cache initialize issue on 4KEc (MIPS32r2)

来自Jack's Lab
跳转到: 导航, 搜索

1 Phenomenon

Initialize the 4KEc's cache like following code in head.S:

    li       a0, 0x2000      # icache size is 8KB
    lui     a2, 0x8000
    addu    a3, a2, a0
   
21:
    cache   Index_Store_Tag_I, 0(a2)
    addiu   a2, 16
    ble     a2, a3, 21b
    nop

    /* setup dcache */
    lui     a2, 0x8000
    li       a0, 0x2000      # dcache size is also 8KB
    addu    a3, a2, a0
22:
    cache   Index_Store_Tag_D, 0(a2)
    addiu   a2, 16
    ble     a2, a3, 22b
    nop

Above code defined in kernel_entry_setup (include/asm/mach-emma3p/kernel-entry-init.h)

The kernel can not boot up properly (No printk out, serial console can not be used).



2 Analysis

Removed the setup_cache code the kernel can boot up properly.
Add Led support(asm) for indicating where the executing point is. By this way I found that the head.S executed properly but when executing stream enter the start_kernel the kernel would enter an unknown path.


Think about the cache initializing code issue

Modify the icache initializing like this:

  Index_Store_Tag_I   ---> Fill ---> Index_Store_Tag_I
    li      a0, 0x2000
    lui     a2, 0x8000
    addu    a3, a2, a0
    move    k0, a2

21:
    cache   Index_Store_Tag_I, 0(a2)
    addiu   a2, 16
    ble     a2, a3, 21b
    nop

20:
    cache   Fill, 0(k0)
    addiu   k0, 16
    ble     k0, a3, 20b
    nop

    li      a2, KSEG0
25:
    cache   Index_Store_Tag_I, 0(a2)
    addiu   a2, 16
    ble     a2, a3, 25b
    nop


Modify the dcache initializing code like this:

  Index_Store_Tag_D ---> load ---> Index_Store_Tag_D
    lui     a2, 0x8000
    li      a0, 0x2000
    addu    a3, a2, a0
    move    k0, a2
22:
    cache   Index_Store_Tag_D, 0(a2)
    addiu   a2, 16
    ble     a2, a3, 22b
    nop

23:
    lw      t3, 0(k0)
    addiu   k0, 16
    ble     k0, a3, 23b
    nop

    lui     a2, 0x8000
24:
    cache   Index_Store_Tag_D, 0(a2)
    addiu   a2, 16
    ble     a2, a3, 24b
    nop

The issue is also exist.


Doubt the Index_* cache ops function

Add the following initializing code:

    /* initialize way select array */

    li           k0, 0x0400            # TagLo[15:10] is LRU bit
    mtc0    k0, CP0_TAGLO

    /* enable ws */
    lui         k0, 0x2000
    mtc0    k0, $26         # CP0_ErrCtl
    ssnop
    ssnop
    ssnop
    sll     zero, 3

    li      a0, 0x1000
    li      a2, KSEG0
    addu    a3, a2, a0
    /* set way select value is 1 */
28:
    cache   Index_Store_Tag_I, 0(a2)
    cache   Index_Store_Tag_D, 0(a2)
    addu    a2, 16
    bne     a2, a3, 28b
    nop

    mtc0    zero, CP0_TAGLO

    /* clear way 1 tag */
    li      a0, 0x1000
    li      a2, KSEG0
    addu    a3, a2, a0
28:
    cache   Index_Store_Tag_I, 0(a2)
    cache   Index_Store_Tag_D, 0(k0)
    addu    a2, 16
    bne     a2, a3, 28b
    nop    

    /* disable ws */
    mtc0    zero, $26
    ssnop
    ssnop
    ssnop
    sll     zero, 3

The issue is also exist.


By Chance

When I enable_cached in the end of setup_cache macro and disable_cached before the j start_kernel the kernel can boot up properly.

I moved the enable_cached/disable_cached pair and found that the issue is disappear so long as the pair braket following code block:

    enable_cached

    LONG_S     a0, fw_arg0     # firmware arguments
    LONG_S     a1, fw_arg1
    LONG_S     a2, fw_arg2
    LONG_S     a3, fw_arg3

    disable_cached

I reviewed the setup_cp0 and setup_cache macro defined in include/asm-mips/mach-emma3p/subcore-init.h and found that they use the a0, a2 and a3 register and these vaules is also up 0x8000_0000. So the kernel get the incorrect value and make the kernel enter an unknown path.



3 Solution

Don't use these register before they are saved in fw_argx.













个人工具
名字空间

变换
操作
导航
工具箱