免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 19363 | 回复: 10
打印 上一主题 下一主题

[FreeBSD] Freebsd10.1-X64-创建内核页表-函数create_pagetables [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-03-21 23:41 |只看该作者 |倒序浏览
本帖最后由 71v5 于 2015-03-21 23:45 编辑

错误的地方麻烦各位大牛及时指出啊.

内存管理采用逐个击破的方法,最后来个大统一,应该就明白内存等的初始化过程,现在大家看起来估计有点没有头绪哈.

下面部分图摘自intel手册,对于使用direct map和映射kernel自身的PML4-table的宏或者函数没有去分析,
不过有了大概的结构,相信这些宏或者函数会比较简单.

Every paging structure is 4096 Bytes in size and comprises a number of individual entries. With 32-bit paging,
each entry is 32 bits (4 bytes); there are thus 1024 entries in each structure. With PAE paging and IA-32e paging,
each entry is 64 bits (8 bytes); there are thus 512 entries in each structure. (PAE paging includes one exception, a
paging structure that is 32 bytes in size, containing 4 64-bit entries.)

  1. [函数create_pagetables]:
  2.         /*
  3.                  * 参数firstaddr:
  4.                  * kernel后第一个可用物理地址.
  5.                  *
  6.                  * 每一次调用allocpages函数,firstaddr都会被更新.
  7.                  */
  8.    685        static void
  9.    686        create_pagetables(vm_paddr_t *firstaddr)
  10.    687        {
  11.    688                int i, j, ndm1g, nkpdpe;
  12.    689                pt_entry_t *pt_p;
  13.    690                pd_entry_t *pd_p;
  14.    691                pdp_entry_t *pdp_p;
  15.    692                pml4_entry_t *p4_p;
  16.    693       
  17.    694                /* Allocate page table pages for the direct map */
  18.             /*
  19.                          * #define        PDPSHIFT        30                LOG2(NBPDP)
  20.                          * #define        NBPDP                (1<<PDPSHIFT) bytes/page dir ptr table
  21.                          *
  22.                          * ndmpdp:
  23.                          * 该变量以1G为单位描述了系统中可以direct map的内存,可以
  24.                          * 理解为Page-Directory-Pointer-Table中entry的数目,同时
  25.                          * 间接指定了Page-Directory的数目.
  26.                          * 因为是64位系统,将ndmpdp的最小值限制为4,即4G.
  27.                          */
  28.    695                ndmpdp = (ptoa(Maxmem) + NBPDP - 1) >> PDPSHIFT;
  29.    696                if (ndmpdp < 4)                /* Minimum 4GB of dirmap */
  30.    697                        ndmpdp = 4;
  31.             /*
  32.                          * Every paging structure is 4096 Bytes in size and comprises a number of individual entries
  33.                          *
  34.                          * #define PAGE_SHIFT        12                /* LOG2(PAGE_SIZE) */
  35.                          * #define PAGE_SIZE        (1<<PAGE_SHIFT)        /* bytes/page */
  36.                          *
  37.                          * 宏NPDPEPG:
  38.                          * #define        NPDPEPG                (PAGE_SIZE/(sizeof (pdp_entry_t))) 这里为512
  39.                          * 每个大小为PAGE_SIZE的page包含多少个Page-Directory-Pointer-Table Entry
  40.                          * ,每个Page-Directory-Pointer-Table Entry的大小为64bit.
  41.                          *
  42.                          * ndmpdpphys:Page-Directory-Pointer-Table的数目,同时间接指定了
  43.                          * PML4-table中entry的数目.
  44.                          *
  45.                          * 699-708:
  46.                          * #define        NDMPML4E        8
  47.                          * NDMPML4E is the maximum number of PML4 entries that will be
  48.              * used to implement the direct map.
  49.                          * PML4-table中一个entry可以确定512G的内存,在这里,可以direct map
  50.                          * 的系统内存大小限制为8*512.
  51.                          */
  52.    698                ndmpdpphys = howmany(ndmpdp, NPDPEPG);
  53.    699                if (ndmpdpphys > NDMPML4E) {
  54.    700                        /*
  55.    701                         * Each NDMPML4E allows 512 GB, so limit to that,
  56.    702                         * and then readjust ndmpdp and ndmpdpphys.
  57.                  *
  58.    703                         */
  59.    704                        printf("NDMPML4E limits system to %d GB\n", NDMPML4E * 512);
  60.    705                        Maxmem = atop(NDMPML4E * NBPML4);
  61.    706                        ndmpdpphys = NDMPML4E;
  62.    707                        ndmpdp = NDMPML4E * NPDEPG;
  63.    708                }
  64.             /*
  65.                          * DMPDPphys:在direct map下,Page-Directory-Pointer-Table
  66.                          * 的起始物理地址,分配大小为(ndmpdpphys * PAGE_SIZE)的内存
  67.                          * 空间用来保存Page-Directory-Pointer-Table.
  68.                          *
  69.                          * DMPDphys:在direct map下,Page-Directory的起始物理地址,
  70.                          * 即分配大小为((ndmpdp - ndm1g) * PAGE_SIZE)的内存空间用来
  71.                          * 保存Page-Directory.
  72.                          *
  73.                          * 在支持大小为1G的page时:
  74.                          * ndm1g:以1G为单位描述系统内存大小,此时ndm1g非零.
  75.                          * 保存在DMPDphys处的Page-Directory以2M的page映射
  76.                          * [ndm1g<<PDPSHIFT,ndmpdp<<PDPSHIFT]之间的内存.
  77.                          * [0,ndm1g<<PDPSHIFT]之间的内存以1G的page进行映射.
  78.                          *
  79.                          * 在不支持大小为1G的page时;
  80.                          * ndm1g:以1G为单位描述系统内存大小,此时ndm1g为零.                         
  81.                          * 保存在DMPDphys处的Page-Directory以2M的page映射
  82.                          * [ndm1g<<PDPSHIFT,ndmpdp<<PDPSHIFT]之间的内存.
  83.                          *
  84.                          * dmaplimit:系统对可以direct map的内存大小进行了限制.                         
  85.                          */
  86.    709                DMPDPphys = allocpages(firstaddr, ndmpdpphys);
  87.    710                ndm1g = 0;
  88.             /*
  89.                          * #define        AMDID_PAGE1GB        0x04000000
  90.                          * #define        PDPSHIFT        30
  91.                          */
  92.    711                if ((amd_feature & AMDID_PAGE1GB) != 0)
  93.    712                        ndm1g = ptoa(Maxmem) >> PDPSHIFT;
  94.    713                if (ndm1g < ndmpdp)
  95.    714                        DMPDphys = allocpages(firstaddr, ndmpdp - ndm1g);
  96.    715                dmaplimit = (vm_paddr_t)ndmpdp << PDPSHIFT;
  97.    716       
  98.    717                /* Allocate pages */
  99.                         /*
  100.                          * #define NKPML4E                4
  101.                          *
  102.                          * KPML4phys:PML4-table的起始物理地址,分配一个大小为PAGE_SIZE的内存
  103.                          * 空间用来保存PML4-table.
  104.                          *
  105.                          * KPDPphys:Page-Directory-Pointer-Table的起始物理地址,分配一个大小为
  106.                          * NKPML4E*PAGE_SIZE的内存空间用来保存Page-Directory-Pointer-Table.
  107.                          *
  108.                          * 同时也可以看出,kernel在PML4-table中占用4个entry.
  109.                          */
  110.    718                KPML4phys = allocpages(firstaddr, 1);
  111.    719                KPDPphys = allocpages(firstaddr, NKPML4E);
  112.    720       
  113.    721                /*
  114.    722                 * Allocate the initial number of kernel page table pages required to
  115.    723                 * bootstrap.  We defer this until after all memory-size dependent
  116.    724                 * allocations are done (e.g. direct map), so that we don't have to
  117.    725                 * build in too much slop in our estimate.
  118.    726                 *
  119.    727                 * Note that when NKPML4E > 1, we have an empty page underneath
  120.    728                 * all but the KPML4I'th one, so we need NKPML4E-1 extra (zeroed)
  121.    729                 * pages.  (pmap_enter requires a PD page to exist for each KPML4E.)
  122.    730                 */
  123.             /*
  124.                          * 731:
  125.                          * 函数nkpt_init初始化变量nkpt,该变量可以理解为映射物理地址范围[0,*firstaddr]
  126.                          * 需要的Page-Directory-Entry的数目,也间接指定了Page-Table的数目.
  127.                          *
  128.                          * 732:
  129.                          * #define        NPDEPG                (PAGE_SIZE/(sizeof (pd_entry_t))) 这里为512
  130.                          * #define        NKPDPE(ptpgs)                howmany((ptpgs), NPDEPG)
  131.                          *
  132.                          * nkpdpe的含义为:保存nkpt个Page-Directory-Entry需要的paging structure的数目或者
  133.                          * 为Page-Directory的数目,该变量同时间接指定了Page-Directory-Pointer-Table中entry的数目.
  134.                          */
  135.    731                nkpt_init(*firstaddr);
  136.    732                nkpdpe = NKPDPE(nkpt);
  137.    733            /*
  138.              * KPTphys:Page-Table的起始物理地址.
  139.                          * KPDphys:Page-Directory-Table的起始物理地址.
  140.                          * 个人感觉这里的函数调用顺序应该为:
  141.                          *  KPDphys = allocpages(firstaddr, nkpdpe);
  142.                          *  KPTphys = allocpages(firstaddr, nkpt);
  143.                          */
  144.    734                KPTphys = allocpages(firstaddr, nkpt);
  145.    735                KPDphys = allocpages(firstaddr, nkpdpe);
  146.    736       
  147.    737                /* Fill in the underlying page table pages */
  148.    738                /* Nominally read-only (but really R/W) from zero to physfree */
  149.    739                /* XXX not fully used, underneath 2M pages */
  150.             /* 填充页表项 */
  151.    740                pt_p = (pt_entry_t *)KPTphys;
  152.    741                for (i = 0; ptoa(i) < *firstaddr; i++)
  153.    742                        pt_p[i] = ptoa(i) | X86_PG_RW | X86_PG_V | X86_PG_G;
  154.    743       
  155.    744                /* Now map the page tables at their location within PTmap */
  156.             /*
  157.                          * 填充Page-Directory-Entry,使用4KB的page时。
  158.                          *
  159.                          * 变量nkpt:该变量可以理解为映射物理地址范围[0,*firstaddr]
  160.                          * 需要的Page-Directory-Entry的数目,也间接指定了Page-Table的数目.
  161.                          *
  162.                          * 使用上面已经初始化好的页表充页目录项.
  163.                          */
  164.    745                pd_p = (pd_entry_t *)KPDphys;
  165.    746                for (i = 0; i < nkpt; i++)
  166.    747                        pd_p[i] = (KPTphys + ptoa(i)) | X86_PG_RW | X86_PG_V;
  167.    748       
  168.    749                /* Map from zero to end of allocations under 2M pages */
  169.    750                /* This replaces some of the KPTphys entries above */
  170.             /* #define        PDRSHIFT        21 */
  171.                         /*
  172.                          * 在64位系统下使用2M的page.
  173.                          * 使用2M的page重新填充Page-Directory-Table,
  174.                          * 此时保存在KPTphys位置的Page-Table貌似没有实际用途.
  175.                          */
  176.    751                for (i = 0; (i << PDRSHIFT) < *firstaddr; i++)
  177.    752                        pd_p[i] = (i << PDRSHIFT) | X86_PG_RW | X86_PG_V | PG_PS |
  178.    753                            X86_PG_G;
  179.    754       
  180.    755                /* And connect up the PD to the PDP (leaving room for L4 pages) */
  181.             /*
  182.                          * #define        NPML4EPG        (PAGE_SIZE/(sizeof (pml4_entry_t))) 这里为512
  183.                          * #define  NKPML4E                4
  184.                          * #define        KPML4BASE        (NPML4EPG-NKPML4E) 508
  185.                          * #define        KPML4I                (NPML4EPG-1) 511
  186.                          *
  187.                          * #define        NPDPEPG                (PAGE_SIZE/(sizeof (pdp_entry_t))) 这里为512
  188.                          * #define        KPDPI                (NPDPEPG-2)  510 kernbase at -2GB
  189.                          *
  190.                          * nkpdpe的含义为:保存nkpt个Page-Directory-Entry需要的paging structure的数目或者
  191.                          * 为Page-Directory的数目,该变量同时间接指定了Page-Directory-Pointer-Table中entry的数目.
  192.                          *
  193.                          * KPDPphys:Page-Directory-Pointer-Table的起始物理地址
  194.                          * pdp_p:(pdp_entry_t *)(KPDPphys + ptoa(KPML4I - KPML4BASE));
  195.                          *
  196.                          * kernel在第三个Page-Directory-Pointer-Table中进行映射.
  197.                          */
  198.    756                pdp_p = (pdp_entry_t *)(KPDPphys + ptoa(KPML4I - KPML4BASE));
  199.    757                for (i = 0; i < nkpdpe; i++)
  200.    758                        pdp_p[i + KPDPI] = (KPDphys + ptoa(i)) | X86_PG_RW | X86_PG_V |
  201.    759                            PG_U;
  202.    760       
  203.    761                /*
  204.    762                 * Now, set up the direct map region using 2MB and/or 1GB pages.  If
  205.    763                 * the end of physical memory is not aligned to a 1GB page boundary,
  206.    764                 * then the residual physical memory is mapped with 2MB pages.  Later,
  207.    765                 * if pmap_mapdev{_attr}() uses the direct map for non-write-back
  208.    766                 * memory, pmap_change_attr() will demote any 2MB or 1GB page mappings
  209.    767                 * that are partially used.
  210.    768                 */
  211.             /*
  212.                          * #define        NPDEPG                (PAGE_SIZE/(sizeof (pd_entry_t))) 这里为512.
  213.                          * #define        PDRSHIFT        21
  214.                          *
  215.                          * ndmpdp:
  216.                          * 该变量以1G为单位描述了系统中全部可以用内存,可以
  217.                          * 理解为Page-Directory-Pointer-Table中entry的数目,同时
  218.                          * 间接指定了Page Directory的数目. NPDEPG * ndmpdp为Page-Directory-entry
  219.                          * 的数目,每个Page Directory entry映射2M的page.
  220.                          *
  221.                          */
  222.    769                pd_p = (pd_entry_t *)DMPDphys;
  223.    770                for (i = NPDEPG * ndm1g, j = 0; i < NPDEPG * ndmpdp; i++, j++) {
  224.    771                        pd_p[j] = (vm_paddr_t)i << PDRSHIFT;
  225.    772                        /* Preset PG_M and PG_A because demotion expects it. */
  226.    773                        pd_p[j] |= X86_PG_RW | X86_PG_V | PG_PS | X86_PG_G |
  227.    774                            X86_PG_M | X86_PG_A;
  228.    775                }
  229.             /*
  230.                          * #define        PDPSHIFT        30                LOG2(NBPDP)
  231.                          * 在支持大小为1G的page时,ndm1g非零:
  232.                          * 此时776-782:填充Page-Directory-Pointer-Table,这部分entry直接映射
  233.                          * 1G大小的page.
  234.                          * 783-786:映射Page Directory
  235.                          *
  236.                          * 在不支持大小为1G的page时,ndm1g为零:
  237.                          * 783-786:映射Page Directory
  238.                          */
  239.    776                pdp_p = (pdp_entry_t *)DMPDPphys;
  240.    777                for (i = 0; i < ndm1g; i++) {
  241.    778                        pdp_p[i] = (vm_paddr_t)i << PDPSHIFT;
  242.    779                        /* Preset PG_M and PG_A because demotion expects it. */
  243.    780                        pdp_p[i] |= X86_PG_RW | X86_PG_V | PG_PS | X86_PG_G |
  244.    781                            X86_PG_M | X86_PG_A;
  245.    782                }
  246.    783                for (j = 0; i < ndmpdp; i++, j++) {
  247.    784                        pdp_p[i] = DMPDphys + ptoa(j);
  248.    785                        pdp_p[i] |= X86_PG_RW | X86_PG_V | PG_U;
  249.    786                }
  250.    787       
  251.    788                /* And recursively map PML4 to itself in order to get PTmap */
  252.             /*
  253.                          * #define        NPML4EPG        (PAGE_SIZE/(sizeof (pml4_entry_t))) 这里为512
  254.                          * #define        PML4PML4I        (NPML4EPG/2)        Index of recursive pml4 mapping 这里为256
  255.                          * p4_p[PML4PML4I]映射自身.
  256.                          */
  257.    789                p4_p = (pml4_entry_t *)KPML4phys;
  258.    790                p4_p[PML4PML4I] = KPML4phys;
  259.    791                p4_p[PML4PML4I] |= X86_PG_RW | X86_PG_V | PG_U;
  260.    792       
  261.    793                /* Connect the Direct Map slot(s) up to the PML4. */
  262.             /*
  263.                          * 在direct map下:
  264.                          * ndmpdpphys:Page-Directory-Pointer-Table的数目,同时间接指定了
  265.                          * PML4-table中entry的数目.
  266.                          *
  267.                          * DMPDPphys:在direct map下,Page-Directory-Pointer-Table
  268.                          * 的起始物理地址,分配大小为(ndmpdpphys * PAGE_SIZE)的内存
  269.                          * 空间用来保存Page-Directory-Pointer-Table.
  270.                          *
  271.                          * #define        KPML4BASE        (NPML4EPG-NKPML4E) 508
  272.                          * #define        NDMPML4E        8
  273.                          * NDMPML4E is the maximum number of PML4 entries that will be
  274.              * used to implement the direct map
  275.                          * #define        DMPML4I                rounddown(KPML4BASE-NDMPML4E, NDMPML4E)
  276.                          *
  277.                          * 近似为index从500开始的PML4 table entry进行映射.
  278.                          */
  279.    794                for (i = 0; i < ndmpdpphys; i++) {
  280.    795                        p4_p[DMPML4I + i] = DMPDPphys + ptoa(i);
  281.    796                        p4_p[DMPML4I + i] |= X86_PG_RW | X86_PG_V | PG_U;
  282.    797                }
  283.    798       
  284.    799                /* Connect the KVA slots up to the PML4 */
  285.             /*
  286.                          * #define NKPML4E                4
  287.                          * #define        KPML4BASE        (NPML4EPG-NKPML4E) 508
  288.                          * 从index为508开始映射.
  289.                          */
  290.    800                for (i = 0; i < NKPML4E; i++) {
  291.    801                        p4_p[KPML4BASE + i] = KPDPphys + ptoa(i);
  292.    802                        p4_p[KPML4BASE + i] |= X86_PG_RW | X86_PG_V | PG_U;
  293.    803                }
复制代码

论坛徽章:
54
2017金鸡报晓
日期:2017-02-08 10:39:42操作系统版块每日发帖之星
日期:2016-03-08 06:20:00操作系统版块每日发帖之星
日期:2016-03-07 06:20:00操作系统版块每日发帖之星
日期:2016-02-22 06:20:00操作系统版块每日发帖之星
日期:2016-01-29 06:20:00操作系统版块每日发帖之星
日期:2016-01-27 06:20:00操作系统版块每日发帖之星
日期:2016-01-20 06:20:00操作系统版块每日发帖之星
日期:2016-01-06 06:20:0015-16赛季CBA联赛之江苏
日期:2015-12-21 20:00:24操作系统版块每日发帖之星
日期:2015-12-21 06:20:00IT运维版块每日发帖之星
日期:2015-11-17 06:20:002015亚冠之广州恒大
日期:2015-11-12 10:58:02
2 [报告]
发表于 2015-03-22 12:21 |只看该作者
高大上啊!
只能从精神是支持一下

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
3 [报告]
发表于 2015-03-22 22:19 |只看该作者
必须给楼主站岗。

论坛徽章:
7
2015年中国系统架构师大会
日期:2015-06-26 14:01:38技术图书徽章
日期:2015-12-15 16:42:2715-16赛季CBA联赛之辽宁
日期:2015-12-16 11:01:33shanzhi
日期:2016-06-17 17:59:312017金鸡报晓
日期:2017-01-10 15:19:562017金鸡报晓
日期:2017-02-08 10:39:42
4 [报告]
发表于 2015-03-24 23:22 |只看该作者

论坛徽章:
40
水瓶座
日期:2013-08-15 11:26:422015年辞旧岁徽章
日期:2015-03-03 16:54:152015年亚洲杯之乌兹别克斯坦
日期:2015-03-27 14:01:172015年亚洲杯之约旦
日期:2015-03-31 15:06:442015亚冠之首尔
日期:2015-06-16 23:24:37IT运维版块每日发帖之星
日期:2015-07-01 22:20:002015亚冠之德黑兰石油
日期:2015-07-08 09:32:07IT运维版块每日发帖之星
日期:2015-08-29 06:20:00IT运维版块每日发帖之星
日期:2015-08-29 06:20:00IT运维版块每日发帖之星
日期:2015-10-10 06:20:00IT运维版块每日发帖之星
日期:2015-10-11 06:20:00IT运维版块每日发帖之星
日期:2015-11-10 06:20:00
5 [报告]
发表于 2015-04-11 18:07 |只看该作者
只能说不明觉厉了  这个真搞不了

论坛徽章:
0
6 [报告]
发表于 2015-04-18 08:10 |只看该作者
路过,帮顶下。。。

论坛徽章:
0
7 [报告]
发表于 2015-05-13 01:46 |只看该作者
怎么回事。。。。

论坛徽章:
0
8 [报告]
发表于 2015-05-26 16:46 |只看该作者
大神啊!看都看不懂

论坛徽章:
0
9 [报告]
发表于 2015-05-26 16:47 |只看该作者

论坛徽章:
0
10 [报告]
发表于 2015-08-18 13:39 |只看该作者
神啊,我看不懂,膜拜!!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP