pfn_to_page

kernel: 5.10
arch: arm64

VMEMMAP区域存放的的是struct page结构体,pfn_to_page实际就是通过物理页帧号来从VMEMMAP区域索引到对应的struct page结构体

在这里插入图片描述

 #define pfn_to_page __pfn_to_page

对于定义了CONFIG_SPARSEMEM_VMEMMAP宏,则

#define __pfn_to_page(pfn)      (vmemmap + (pfn))

注意pfn是按照实际的物理地址编号的,如本例中物理内存起始地址为0x40000000,起始物理页帧号为0x40000

vmemmap 定义如下:

#define vmemmap                 ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT))

memstart_addr为物理地址0x40000000,从打印上看vmemmap为0xfffffdfffee00000,它就是用来存放struct page结构体的虚拟空间起始地址偏移(memstart_addr >> PAGE_SHIFT),为何会有这个偏移?原因是实际物理页帧号是根据实际的物理地址计算的,并非从0开始,当然也可以将vmemmap理解成是物理地址0x0对应的struct page所在的位置,只不过内存物理地址一般不是从0x0开始。

#define SZ_2M                           0x00200000
#define VMEMMAP_START           (-VMEMMAP_SIZE - SZ_2M)

通过打印看VMEMMAP_START:0xfffffdffffe00000,它位于虚拟地址空间PCI I/O区间以上,不知道VMEMMAP_START为何会这样计算?它就是VMEMMAP空间的起始地址

#define _PAGE_END(va)           (-(UL(1) << ((va) - 1)))
#define VA_BITS_MIN             (VA_BITS)
#define VA_BITS                 (CONFIG_ARM64_VA_BITS) 
/*
 * VMEMMAP_SIZE - allows the whole linear region to be covered by                                                                                               
 *                a struct page array                                                                                                                           
 *
 * If we are configured with a 52-bit kernel VA then our VMEMMAP_SIZE                                                                                           
 * needs to cover the memory region from the beginning of the 52-bit                                                                                            
 * PAGE_OFFSET all the way to PAGE_END for 48-bit. This allows us to
 * keep a constant PAGE_OFFSET and "fallback" to using the higher end                                                                                           
 * of the VMEMMAP where 52-bit support is not available in hardware.                                                                                            
 */
#define VMEMMAP_SIZE ((_PAGE_END(VA_BITS_MIN) - PAGE_OFFSET) \
                        >> (PAGE_SHIFT - STRUCT_PAGE_MAX_SHIFT))

通过打印_PAGE_END(VA_BITS_MIN)可以得到虚拟地址为:0xffff800000000000也就是线性映射区的结束地址,而PAGE_OFFSET为线性映射区的起始地址,PAGE_SHIFT - STRUCT_PAGE_MAX_SHIFT代表一个页可以存放多少个struct page结构体,因此整体VMEMMAP_SIZE就表示线性影射区需要多少页大小的空间来存放struct page结构体

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值