栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

for

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

for

kenrel: 5.10
arch: aarch64

启动阶段经过arm64_memblock_init之后,通过gdb可以查看到memblock布局如下,此处的memblock可以理解为在线的memory

(gdb) p/x memblock
$5 = {
  bottom_up = 0x0,
  current_limit = 0xffffffffffffffff,
  memory = {
    cnt = 0x1,
    max = 0x80,
    total_size = 0x40000000,
    regions = 0xffff8000120a8848,
    name = 0xffff80001139cc28
  },
  reserved = {
    cnt = 0x5,
    max = 0x181,
    total_size = 0x58a20c4,
    regions = 0xffff8000120a9448,
    name = 0xffff80001127e258
  }
}

其中memblock.memory如下:

(gdb) p/x *(struct memblock_region *)0xffff8000120a8848
$6 = {
  base = 0x40000000,
  size = 0x40000000,
  flags = 0x0,
  nid = 0x10
}

memblock.reserved如下:

(gdb) p/x *(struct memblock_region *)0xffff8000120a9448@5
$9 =   {{
    base = 0x40200000,
    size = 0x2592000,
    flags = 0x0,
    nid = 0x10
  },
  {
    base = 0x42797000,
    size = 0x9000,
    flags = 0x0,
    nid = 0x10
  },
  {
    base = 0x48000000,
    size = 0x100000,
    flags = 0x0,
    nid = 0x10
  },
  {
    base = 0x7cdf8f38,
    size = 0x90c4,
        flags = 0x0,
    nid = 0x10
  },
  {
    base = 0x7ce02000,
    size = 0x31fe000,
    flags = 0x0,
    nid = 0x10
  }}

从如上可以看出,只有一个memory区域,5个reserved区域

__next_mem_pfn_range
void __init_memblock __next_mem_pfn_range(int *idx, int nid,
                                unsigned long *out_start_pfn,
                                unsigned long *out_end_pfn, int *out_nid)
{
        struct memblock_type *type = &memblock.memory;
        struct memblock_region *r;
        int r_nid;

        while (++*idx < type->cnt) {
                r = &type->regions[*idx];
                r_nid = memblock_get_region_node(r);

                if (PFN_UP(r->base) >= PFN_DOWN(r->base + r->size))
                        continue;
                if (nid == MAX_NUMNODES || nid == r_nid)
                        break;
        }
        if (*idx >= type->cnt) {
                *idx = -1;
                return;
        }

        if (out_start_pfn)
                *out_start_pfn = PFN_UP(r->base);
        if (out_end_pfn)
                *out_end_pfn = PFN_DOWN(r->base + r->size);
        if (out_nid)
                *out_nid = r_nid;
}

上面的函数主要是通过遍历memblock.memory下的每个memblock_region区域,找到node id为nid的memblock_region区域将其起始物理地址和结束物理地址转换为物理页帧号分别保存在out_start_pfn和out_end_pfn返回。
注意:物理页帧号与物理地址是紧密关联的,如物理地址为0x40000000,则物理页帧号为0x40000

这里列出memblock, memblock_type, memblock_region 结构体定义,以说明他们之间的关系

struct memblock_region {
        phys_addr_t base;
        phys_addr_t size;
        enum memblock_flags flags;
#ifdef CONFIG_NEED_MULTIPLE_NODES
        int nid;
#endif
};


struct memblock_type {
        unsigned long cnt;
        unsigned long max;
        phys_addr_t total_size;
        struct memblock_region *regions;
        char *name;
};


struct memblock {
        bool bottom_up;  
        phys_addr_t current_limit;
        struct memblock_type memory;
        struct memblock_type reserved;
};
for_each_mem_pfn_range
                                                                                                                                                             
#define for_each_mem_pfn_range(i, nid, p_start, p_end, p_nid)                                                                                                  
        for (i = -1, __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid);                                                                                     
             i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid))

根据前面__next_mem_pfn_range的定义,for_each_mem_pfn_range实际上就是遍历memblock.memory下的每个memblock_region区域,找到node id与参数 nid相等 的memblock_region区域,将它的起始pfn和结束pfn,node id,分别保存在p_start,p_end,p_nid返回。这里注意的是如果nid为MAX_NUMNODES,则表示遍历所有的node

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

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

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