栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

linux kernel中的CPU CACHE策略初始化流程

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

linux kernel中的CPU CACHE策略初始化流程

linux booting过程中会打印CACHE的写机制,打印信息如下:

OF: fdt: Machine model: V2P-CA9
Memory policy: Data cache writealloc

以上打印信息来自于函数
build_mem_type_table(void)
它的调用栈如下:

setup_arch
  |
  #ifdef CONFIG_MMU
    early_mm_init(mdesc);
  #endif
    |
    early_mm_init()
      |
      build_mem_type_table();

build_mem_type_table()函数的功能是获取当前CPU的CACHE类型,据此初始化mem_type。kernel根据mem_types数据结构的值,做后续的其他处理。

由于build_mem_type_table()属于early_mm_init()的一部分,因此,从early_mm_init()入手,逐步解析CACHE的写机制。

early_mm_init(mdesc)

early_mm_init()能否得到执行,取决于当前kernel是否使能了MMU。

该函数的定义位于setup.c中

void __init early_mm_init(const struct machine_desc *mdesc)
{
	build_mem_type_table();
	early_paging_init(mdesc);
}

函数参数是struct machine_desc指针。数据结构machine_desc描述了CPU的硬件信息及一些初始化函数。

struct machine_desc {
	unsigned int		nr;
	const char		*name;
	unsigned long		atag_offset;
	const char *const 	*dt_compat;
	unsigned int		nr_irqs;

#ifdef CONFIG_ZONE_DMA
	phys_addr_t		dma_zone_size;
#endif
	unsigned int		video_start;
	unsigned int		video_end;
	unsigned char		reserve_lp0 :1;
	unsigned char		reserve_lp1 :1;
	unsigned char		reserve_lp2 :1;
	enum reboot_mode	reboot_mode;
	unsigned		l2c_aux_val;
	unsigned		l2c_aux_mask;
	void			(*l2c_write_sec)(unsigned long, unsigned);
	const struct smp_operations	*smp;
	bool			(*smp_init)(void);
	void			(*fixup)(struct tag *, char **);
	void			(*dt_fixup)(void);
	long long		(*pv_fixup)(void);
	void			(*reserve)(void);
	void			(*map_io)(void);
	void			(*init_early)(void);
	void			(*init_irq)(void);
	void			(*init_time)(void);
	void			(*init_machine)(void);
	void			(*init_late)(void);
#ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
	void			(*handle_irq)(struct pt_regs *);
#endif
	void			(*restart)(enum reboot_mode, const char *);
};

通过解析设备树镜像得到mdesc成员的具体值是什么。

if (atags_vaddr) {
	mdesc = setup_machine_fdt(atags_vaddr);
	if (mdesc)
		memblock_reserve(__atags_pointer,
				 fdt_totalsize(atags_vaddr));
}	
build_mem_type_table()

这个函数的核心作用是初始化struct mem_type数据结构,定义如下:

struct mem_type {
	pteval_t prot_pte;
	pteval_t prot_pte_s2;
	pmdval_t prot_l1;
	pmdval_t prot_sect;
	unsigned int domain;
};

该数据结构的历史:

author	Russell King 	2007-04-21 10:47:29 +0100
committer	Russell King 	2007-04-21 20:36:00 +0100
[ARM] mm 5: Use mem_types table in ioremap
We really want to be using the memory type table in ioremap, so we
only have to do the CPU type fixups in one place.

Signed-off-by: Russell King 

Diffstat (limited to 'arch/arm/mm/mm.h')
-rw-r--r--	arch/arm/mm/mm.h	9	
		
1 files changed, 9 insertions, 0 deletions
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index a44e309706354..66f8612c5e5b9 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
+struct mem_type {
+	unsigned int prot_pte;
+	unsigned int prot_l1;
+	unsigned int prot_sect;
+	unsigned int domain;
+};
+
+const struct mem_type *get_mem_type(unsigned int type);
+

从commit信息中可以看到,struct mem_type最初的目的是给ioremap使用的,在这个patch中,增加了struct mem_type以及get_mem_type()。

到目前为止,这个数据结构的作用已经不仅限上面提及的内容。更为主要的作用是根据mem类型创建内核页表。

build_mem_type_table()函数根据ARM内核版本号例化不同的mem类型。 包括ARM v5/6/7。

int cpu_arch = cpu_architecture();

在mmu.c的init_default_cache_policy中会对cachepolicy进行初始化。

mmu.c (archarmmm) line 64 : static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
init_default_cache_policy in mmu.c (archarmmm) : 			cachepolicy = i;

根据不同的CPU 架构类型对cachepolicy变量重新赋值。

build_mem_type_table in mmu.c (archarmmm) : 		if (cachepolicy > CPOLICY_BUFFERED)
build_mem_type_table in mmu.c (archarmmm) : 			cachepolicy = CPOLICY_BUFFERED;
build_mem_type_table in mmu.c (archarmmm) : 		if (cachepolicy > CPOLICY_WRITETHROUGH)
build_mem_type_table in mmu.c (archarmmm) : 			cachepolicy = CPOLICY_WRITETHROUGH;
build_mem_type_table in mmu.c (archarmmm) : 		if (cachepolicy >= CPOLICY_WRITEALLOC)
build_mem_type_table in mmu.c (archarmmm) : 			cachepolicy = CPOLICY_WRITEBACK;
build_mem_type_table in mmu.c (archarmmm) : 		if (cachepolicy != CPOLICY_WRITEALLOC) {
build_mem_type_table in mmu.c (archarmmm) : 			cachepolicy = CPOLICY_WRITEALLOC;

内核中定义了4中CACHE 写策略,分别是:

#define CPOLICY_BUFFERED	1
#define CPOLICY_WRITETHROUGH	2
#define CPOLICY_WRITEBACK	3
#define CPOLICY_WRITEALLOC	4

最后,根据cachepolicy的值例化数据结构struct cachepolicy *cp,

cp = &cache_policies[cachepolicy];

在我的环境中,cachepolicy的值为4,其对应的CACHE属性为writealloc。

static struct cachepolicy cache_policies[] __initdata = {
	{
		.policy		= "uncached",
		.cr_mask	= CR_W|CR_C,
		.pmd		= PMD_SECT_UNCACHED,
		.pte		= L_PTE_MT_UNCACHED,
		.pte_s2		= s2_policy(L_PTE_S2_MT_UNCACHED),
	}, {
		.policy		= "buffered",
		.cr_mask	= CR_C,
		.pmd		= PMD_SECT_BUFFERED,
		.pte		= L_PTE_MT_BUFFERABLE,
		.pte_s2		= s2_policy(L_PTE_S2_MT_UNCACHED),
	}, {
		.policy		= "writethrough",
		.cr_mask	= 0,
		.pmd		= PMD_SECT_WT,
		.pte		= L_PTE_MT_WRITETHROUGH,
		.pte_s2		= s2_policy(L_PTE_S2_MT_WRITETHROUGH),
	}, {
		.policy		= "writeback",
		.cr_mask	= 0,
		.pmd		= PMD_SECT_WB,
		.pte		= L_PTE_MT_WRITEBACK,
		.pte_s2		= s2_policy(L_PTE_S2_MT_WRITEBACK),
	}, {
		.policy		= "writealloc",
		.cr_mask	= 0,
		.pmd		= PMD_SECT_WBWA,
		.pte		= L_PTE_MT_WRITEALLOC,
		.pte_s2		= s2_policy(L_PTE_S2_MT_WRITEBACK),
	}
};

writealloc结合了write back的功能,而write back是在CACHE hit时所采取的策略,alloc是在CACHE miss所采取的策略,当发生CACHE miss时,会从主存中读取数据并更新CACHE line到CACHE缓存中。对于SMP ARM而言,普遍采取的是这种CACHE 策略,结合ARM 的SCU完成缓存一致性的处理。可以查看ARM的如下寄存器确定CACHE所支持的策略类型。

CACHE写策略

下图是一个标准的ARM处理器的芯片版图布局,使用SRAM作为L1 CACHE,它在ARM core这一区域。通过DDR SDRAM interface访问位于芯片外部的主存DDR memory。简单而论,从二者布局布线的角度看,访问外部DDR memory的cycle明显高于内部L1 CACHE。

当CPU执行数据写操作时,首先检查待写入的内存地址是否在CACHE中,若在CACHE中则称之为Hit,反之为Miss。在Hit命中的前提下,CACHE写策略分为Write back和Write through。

Write through

CACHE工作于write through模式时,数据同时更新到CACHE和主存当中。这种操作模式简单可靠,适用于写操作比较少的应用场景,或者预防突然断电的数据恢复机制中。当然,由于同时更新CACHE和外部主存,这种写模式的延时比较大。

Write back

CACHE工作于write through模式时,数据仅更新到CACHE中而不会立即更新到主存。基于Belady’s Anomaly, LRU, FIFO, LIFO等算法,当CACHE中的数据需要被替换时,原数据会被更新到主存当中。在CACHE的每一个block中,使用一个dirty位来标记当前数据是否需要被替换,若dirty位被置位1,则需要将数据更新到主存。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/312981.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号