在 DISCONTIGMEM 内存模型下 , page_to_pfn 与 pfn_to_page 的计算逻辑本质是定位 page 所在的 node 。
通过 pfn_to_nid 根据物理页的 PFN 定位到物理页所在 node。
通过 page_to_nid 根据物理页 struct page 定义到 page 所在 node。
当定位到物理页 struct page 所在 node 之后,和 FLATMEM 内存模型一样。
/* linux-4.9.37/include/asm-generic/memory_model.h */
#define page_to_pfn __page_to_pfn
#define pfn_to_page __pfn_to_page
#define arch_pfn_to_nid(pfn) pfn_to_nid(pfn)
#define arch_local_page_offset(pfn, nid) \
((pfn) - NODE_DATA(nid)->node_start_pfn)
#define __pfn_to_page(pfn) \
({ unsigned long __pfn = (pfn); \
unsigned long __nid = arch_pfn_to_nid(__pfn); \
NODE_DATA(__nid)->node_mem_map + arch_local_page_offset(__pfn, __nid);\
})
#define __page_to_pfn(pg) \
({ const struct page *__pg = (pg); \
struct pglist_data *__pgdat = NODE_DATA(page_to_nid(__pg)); \
(unsigned long)(__pg - __pgdat->node_mem_map) + \
__pgdat->node_start_pfn; \
})
/* linux-4.9.37/arch/arm64/include/asm/mmzone.h */
extern struct pglist_data *node_data[];
#define NODE_DATA(nid) (node_data[(nid)])
/* linux-4.9.37/include/linux/mmzone.h */
#define pfn_to_nid(pfn) \
({ \
unsigned long __pfn_to_nid_pfn = (pfn); \
page_to_nid(pfn_to_page(__pfn_to_nid_pfn)); \
})
/* linux-4.9.37/include/linux/mm.h */
static inline int page_to_nid(const struct page *page)
{
return (page->flags >> NODES_PGSHIFT) & NODES_MASK;
}
862

被折叠的 条评论
为什么被折叠?



