1 固定映射
1.1 数据结构
linux高端内存中的临时内存区为固定内存区的一部分, 对于固定内存在linux内核中有下面描述
x86 | arm | arm64 |
---|---|---|
arch/x86/include/asm/fixmap.h?v=4.7, line 67 | arch/arm/include/asm/fixmap.h?v=4.7, line 11 | arch/arm64/include/asm/fixmap.h?v=4.7, line 36 |
/*
* Here we define all the compile-time 'special' virtual
* addresses. The point is to have a constant address at
* compile time, but to set the physical address only
* in the boot process.
*
* These 'compile-time allocated' memory buffers are
* page-sized. Use set_fixmap(idx,phys) to associate
* physical memory with fixmap indices.
*
*/
enum fixed_addresses {
FIX_HOLE,
/*
* Reserve a virtual window for the FDT that is 2 MB larger than the
* maximum supported size, and put it at the top of the fixmap region.
* The additional space ensures that any FDT that does not exceed
* MAX_FDT_SIZE can be mapped regardless of whether it crosses any
* 2 MB alignment boundaries.
*
* Keep this at the top so it remains 2 MB aligned.
*/
#define FIX_FDT_SIZE (MAX_FDT_SIZE + SZ_2M)
FIX_FDT_END,
FIX_FDT = FIX_FDT_END + FIX_FDT_SIZE / PAGE_SIZE - 1,
FIX_EARLYCON_MEM_BASE,
FIX_TEXT_POKE0,
__end_of_permanent_fixed_addresses,
/*
* Temporary boot-time mappings, used by early_ioremap(),
* before ioremap() is functional.
*/
#define NR_FIX_BTMAPS (SZ_256K / PAGE_SIZE)
#define FIX_BTMAPS_SLOTS 7
#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS)
FIX_BTMAP_END = __end_of_permanent_fixed_addresses,
FIX_BTMAP_BEGIN = FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1,
/*
* Used for kernel page table creation, so unmapped memory may be used
* for tables.
*/
FIX_PTE,
FIX_PMD,
FIX_PUD,
FIX_PGD,
__end_of_fixed_addresses
};
1.2 固定映射
ioremap
的作用是将IO
和BIOS
以及物理地址空间映射到在896M至1G的128M的地址空间内, 使得kernel能够访问该空间并进行相应的读写操作。
start_kernel()->setup_arch()->early_ioremap_init()
然后arm和arm64上early_ioremap_init
又是early_ioremap_setup
的前端
函数 | x86 | arm | arm64 |
---|---|---|---|
early_ioremap_init | arch/x86/mm/ioremap.c?v=4.7, line 445 | arch/arm/mm/ioremap.c?v=4.7, line 489 | arch/arm64/mm/ioremap.c?v=4.7, line 110 |
early_ioremap_setup | mm/early_ioremap.c?v=4.7, line 67 | 体系结构无关 | 体系结构无关 |
/*
* Must be called after early_fixmap_init
*/
void __init early_ioremap_init(void)
{
early_ioremap_setup();
}
但是arm和arm64下的setup_arch函数则会先调用early_fixmap_init
函数来填充fixmap
. 参见arch/arm/kernel/setup.c?v=4.7, line 1058和arch/arm64/kernel/setup.c?v=4.7, line 229.
void __init setup_arch(char **cmdline_p)
{
early_fixmap_init();
early_ioremap_init();
}
early_fixmap_init
函数的定义在
arm | arm64 |
---|---|
arch/arm/mm/mmu.c?v=4.7, line 385 | arch/arm64/mm/mmu.c?v=4.7, line 676 |
其中arm架构的定义如下所示, 在arch/arm/mm/mmu.c?v=4.7, line 385
void __init early_fixmap_init(void)
{
pmd_t *pmd;
/*
* The early fixmap range spans multiple pmds, for which
* we are not prepared:
*/
BUILD_BUG_ON((__fix_to_virt(__end_of_early_ioremap_region) >> PMD_SHIFT)
!= FIXADDR_TOP >> PMD_SHIFT);
/*得到固定映射区的pmd
,此pmd为虚拟地址转换为物理地址的pmd*/
pmd = fixmap_pmd(FIXADDR_TOP);
/*将bm_pte页表设置为固定映射区开始地址的pmd的第一个页表;*/
pmd_populate_kernel(&init_mm, pmd, bm_pte);
pte_offset_fixmap = pte_offset_early_fixmap;
}
1.3 ioremap函数
对于ioremap
的使用需要通过early_memremap
和early_iounmap
进行.
由于对应于ioremap的内存空间是有限的, 所以对于ioremap空间的使用遵照使用结束马上释放的原则. 这就是说early_memremap和early_iounmap必须配对使用并且访问结束必须马上执行unmap
2 临时内核映射
刚才描述的kmap
函数不能用于中断处理程序,