/home/tnishinaga/TechMEMO

日々行ったこと、面白かったことを書き留めます。

proc-v7m.Sに定義されているnop_cache_fnsはどこにあるのか

ARM Cortex-M7マイコンでキャッシュを使えるようにするためにいろいろ頑張っています。

現在のLinux Kernelでは、アーキテクチャとしてARMv7Mが選択されると同時にCPU_CACHE_NOPが選択*1され、キャッシュを制御するコードとしてarch/arm/mm/cache-nop.S内のコードが利用されるようになっています*2。 このcache-nop.Sにはキャッシュを持たないマイコンのため、キャッシュを操作するための処理として「何もしない(NOP)」というコードが書かれています。 一方、今回対象としているARM Cortex-M7はキャッシュを持つため、このキャッシュを利用するためにはきちんとキャッシュの処理をするコードを書いてあげなければいけません。

さて、このcache-nop.S内の関数はどこでキャッシュを操作する関数として登録されているか調べてみると、proc-v7m.Sにproc_info_list構造体というものがあり、ここのcacheというメンバにセットするとキャッシュを操作する関数として登録されるようです。 以下、proc-v7m.Sの該当部分を引用します。

/*
 * Match any ARMv7-M processor core.
 */
.type   __v7m_proc_info, #object
__v7m_proc_info:
.long   0x000f0000      @ Required ID value
.long   0x000f0000      @ Mask for ID
.long   0           @ proc_info_list.__cpu_mm_mmu_flags
.long   0           @ proc_info_list.__cpu_io_mmu_flags
initfn  __v7m_setup, __v7m_proc_info    @ proc_info_list.__cpu_flush
.long   cpu_arch_name
.long   cpu_elf_name
.long   HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT
.long   cpu_v7m_name
.long   v7m_processor_functions @ proc_info_list.proc
.long   0           @ proc_info_list.tlb
.long   0           @ proc_info_list.user
.long   nop_cache_fns       @ proc_info_list.cache
.size   __v7m_proc_info, . - __v7m_proc_info

ここでproc_info_list.cacheに定義されているnop_cache_fnsシンボルの中身はどこにあるか調べるためgrepをかけてみると、以下のようにproc-v7m.SとSystem.mapにシンボル名は見つかりますが、中身は見つかりません。

$ grep -R "nop_cache_fns" ./
./arch/arm/mm/proc-v7m.S:       .long   nop_cache_fns           @ proc_info_list.cache
Binary file ./arch/arm/mm/cache-nop.o matches
Binary file ./arch/arm/mm/proc-v7m.o matches
Binary file ./arch/arm/mm/built-in.o matches
Binary file ./vmlinux.o matches
Binary file ./.tmp_vmlinux1 matches
Binary file ./.tmp_vmlinux2 matches
Binary file ./vmlinux matches
./System.map:c0128ea0 T nop_cache_fns
./.tmp_System.map:c0128ea0 T nop_cache_f

さっぱりわからないのでcache-nop.Sをじっくり眺めていたところ、以下のような記述を発見しました。

 @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
    define_cache_functions nop

define_cache_functionsはマクロっぽいので、コメントに従ってarch/arm/mm/proc-macros.Sを開いてみると、ビンゴでした。 マクロの定義は以下のようになっており、name部分に設定した名前と_cache_fnsを連結した名前の構造体を作るようになっているようです。 上記の例ではnopがセットされているので、nop_cache_fnsという名前の構造体がこのマクロによって作られることなります。

.macro define_cache_functions name:req
    .align 2
    .type   \name\()_cache_fns, #object
ENTRY(\name\()_cache_fns)
    .long   \name\()_flush_icache_all
    .long   \name\()_flush_kern_cache_all
    .long   \name\()_flush_kern_cache_louis
    .long   \name\()_flush_user_cache_all
    .long   \name\()_flush_user_cache_range
    .long   \name\()_coherent_kern_range
    .long   \name\()_coherent_user_range
    .long   \name\()_flush_kern_dcache_area
    .long   \name\()_dma_map_area
    .long   \name\()_dma_unmap_area
    .long   \name\()_dma_flush_range
    .size   \name\()_cache_fns, . - \name\()_cache_fns
.endm

ちなみにnop_cache_fnsの型はcpu_cache_fnsであり、arch/arm/include/asm/cacheflush.hに定義されています。

とりあえず、以上です。

*1:arch/arm/Kconfig 及び arch/arm/mm/Kconfig を参照

*2:arch/arm/mm/Makefile参照