linux mm 之 DISCONTIGMEM page_to_pfn 与 pfn_to_page

在 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值