close

內核代碼中充斥着大量的__iomem修飾的void類型的指針,像下面這樣:

void__iomem*devm_ioremap_resource(structdevice*dev,conststructresource*res){resource_size_tsize;void__iomem*dest_ptr;char*pretty_name;BUG_ON(!dev);if(!res||resource_type(res)!=IORESOURCE_MEM){dev_err(dev,"invalidresource\n");returnIOMEM_ERR_PTR(-EINVAL);}size=resource_size(res);if(res->name)pretty_name=devm_kasprintf(dev,GFP_KERNEL,"%s%s",dev_name(dev),res->name);elsepretty_name=devm_kstrdup(dev,dev_name(dev),GFP_KERNEL);if(!pretty_name)returnIOMEM_ERR_PTR(-ENOMEM);if(!devm_request_mem_region(dev,res->start,size,pretty_name)){dev_err(dev,"can'trequestregionforresource%pR\n",res);returnIOMEM_ERR_PTR(-EBUSY);}dest_ptr=devm_ioremap(dev,res->start,size);if(!dest_ptr){dev_err(dev,"ioremapfailedforresource%pR\n",res);devm_release_mem_region(dev,res->start,size);dest_ptr=IOMEM_ERR_PTR(-ENOMEM);}returndest_ptr;}

__iomem的定義位於include/linux/compiler_types.h中,規定了GCC相關的一些屬性信息。

#ifdef__CHECKER__#define__user__attribute__((noderef,address_space(1)))#define__kernel__attribute__((address_space(0)))#define__safe__attribute__((safe))#define__force__attribute__((force))#define__nocast__attribute__((nocast))#define__iomem__attribute__((noderef,address_space(2)))#define__must_hold(x)__attribute__((context(x,1,1)))#define__acquires(x)__attribute__((context(x,0,1)))#define__releases(x)__attribute__((context(x,1,0)))#define__acquire(x)__context__(x,1)#define__release(x)__context__(x,-1)#define__cond_lock(x,c)((c)?({__acquire(x);1;}):0)#define__percpu__attribute__((noderef,address_space(3)))#define__rcu__attribute__((noderef,address_space(4)))#define__private__attribute__((noderef))externvoid__chk_user_ptr(constvolatilevoid__user*);externvoid__chk_io_ptr(constvolatilevoid__iomem*);#defineACCESS_PRIVATE(p,member)(*((typeof((p)->member)__force*)&(p)->member))#else/*__CHECKER__*/#ifdefSTRUCTLEAK_PLUGIN#define__user__attribute__((user))#else#define__user#endif#define__kernel#define__safe#define__force#define__nocast#define__iomem#define__chk_user_ptr(x)(void)0#define__chk_io_ptr(x)(void)0#define__builtin_warning(x,y...)(1)#define__must_hold(x)#define__acquires(x)#define__releases(x)#define__acquire(x)(void)0#define__release(x)(void)0#define__cond_lock(x,c)(c)#define__percpu#define__rcu#define__private#defineACCESS_PRIVATE(p,member)((p)->member)#endif/*__CHECKER__*/

__CHECKER__是與Sparse相關的一個宏開關,從kernel頂層Makefile中可以看出,當指定參數C=1或C=2時會調用Sparse。Sparse是2004年由Linus創建的kernel代碼靜態檢查工具。

192#Callasourcecodechecker(bydefault,"sparse")aspartofthe193#Ccompilation.194#195#Use'makeC=1'toenablecheckingofonlyre-compiledfiles.196#Use'makeC=2'toenablecheckingof*all*sourcefiles,regardless197#ofwhethertheyarere-compiledornot.198#199#Seethefile"Documentation/dev-tools/sparse.rst"formoredetails,200#includingwheretogetthe"sparse"utility.

從__CHECKER__和address_space(2)這兩個信息可以看出,當基於Sparse進行通過__iomem修飾的void類型指針需要落到特定地址空間,否則會吐出警告信息。

__iomem存在的意義是kernel系統同時兼容了X86和ARM等類型的處理器平台,對於這兩種典型的處理器平台而言,其寄存器訪問方式是完全不同的。X86架構的處理器是基於IO指令進行寄存器訪問的,而ARM架構的處理器是基於真實存在的32或64位的AMBA總線地址空間來訪問寄存器的。


END

我的微信

--- 往期精彩內容 ---
內核圖顯子系統專輯內核驅動原理專輯內核驅動調試專輯內核及32/64位ARM處理器工作原理專輯
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()