惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Know Your Adversary
Know Your Adversary
N
News and Events Feed by Topic
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Privacy & Cybersecurity Law Blog
P
Privacy International News Feed
Recent Announcements
Recent Announcements
T
Threatpost
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Last Week in AI
Last Week in AI
博客园 - 叶小钗
AWS News Blog
AWS News Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
月光博客
月光博客
The Cloudflare Blog
罗磊的独立博客
P
Palo Alto Networks Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 聂微东
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Tailwind CSS Blog
PCI Perspectives
PCI Perspectives
Forbes - Security
Forbes - Security
Latest news
Latest news
V
Visual Studio Blog
阮一峰的网络日志
阮一峰的网络日志
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
WordPress大学
WordPress大学
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
有赞技术团队
有赞技术团队
N
News and Events Feed by Topic
爱范儿
爱范儿
L
Lohrmann on Cybersecurity
Cisco Talos Blog
Cisco Talos Blog
I
Intezer
S
Secure Thoughts
Hacker News: Ask HN
Hacker News: Ask HN
C
CERT Recently Published Vulnerability Notes
TaoSecurity Blog
TaoSecurity Blog
博客园 - 司徒正美
Google DeepMind News
Google DeepMind News
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Google Online Security Blog
Google Online Security Blog
H
Hacker News: Front Page
Recent Commits to openclaw:main
Recent Commits to openclaw:main
V2EX - 技术
V2EX - 技术
Microsoft Azure Blog
Microsoft Azure Blog
O
OpenAI News
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Webroot Blog
Webroot Blog

博客园 - Edison.Feng

Objective-读Xml [转]iPhone Mapkit 之在地图加入坐标点 使用MKAnnotation和MKAnnotationView [转]Android:使用URL和URLConnection(多线程下载) 【转】httpModules 与 httpHandlers 【转】挣脱浏览器的束缚(2) - 别让脚本引入坏了事 [转]asp.net中利用ashx实现图片防盗链 求任何一个正数的组合,组合的规则是这个数等于1或2的整数幂之和,请列出组合的情况。 C#利用反射获取对象属性的修改情况 C#利用反射获取对象属性值 Clone:Xml序列化反序列克隆对象 [转]Linux slab 分配器剖析 [转]Linux对I/O端口资源的管理 [转]linux内核分析-初始化分析 start_kernel [转]Linux TCP/IP 协议栈的关键数据结构Socket Buffer(sk_buff ) [转]Linux系统内核接收以太帧的处理程序 母牛生小牛(递归) MS SQL:Funcation拆分行 我使用WebService:Function.asmx的惊叹!!!
paging_init
Edison.Feng · 2009-04-27 · via 博客园 - Edison.Feng

paging_init()

 setup.S->start_kernel(void) -> setup_arch -> paging_init()

(1)

   接下来是paging_init,调用下面的pagetable_init,初始化页表然后重新加

载cr3,flush tlb,然后使用kmap_init为kmap_automic使用的变量求值,.....

不算复杂,重要的是free_area_init,初始化了zone-buddy内存管理系统(设置

所有页面都是PG_reserved(free_all_bootmem,负责重置)).

void __init paging_init(void)

{

#ifdef CONFIG_X86_PAE

         set_nx();

         if (nx_enabled)

                 printk("NX (Execute Disable) protection: active\n");

 #endif

         pagetable_init();

         load_cr3(swapper_pg_dir);

 #ifdef CONFIG_X86_PAE

         /*

          * We will bail out later - printk doesn't work right now so

          * the user would just see a hanging kernel.

          */

         if (cpu_has_pae)

                 set_in_cr4(X86_CR4_PAE);

 #endif

         __flush_tlb_all();      //load 了cr3...

         kmap_init();

 }

(2)/mm/init.c

swapper_pg_dir 静态分配的

pgd_t swapper_pg_dir[1024];

//删了config_pae的代码

内核在使用虚拟空间:

+------------------------------------------------------------------     

|   8K空洞

+------------------------------------------------------------------

|   FIXADDR_TOP(0xffffe000UL)            (include/asm-i386/fixmap.h)

|   fixed map(每项4k虚存,见FIXADDR_SIZE)      

|      { //fix map 内容 (enum fixed_addresses)

|         FIX_APIC_BASE, 

|     FIX_IO_APIC_BASE_0,

|   FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1

|   FIX_CO_CPU, /* Cobalt timer */

|   FIX_CO_APIC, /* Cobalt APIC Redirection Table */ 

|   FIX_LI_PCIA, /* Lithium PCI Bridge A */

|   FIX_LI_PCIB, /* Lithium PCI Bridge B */

+--------------

#ifdef CONFIG_HIGHMEM   /*为fix KMAP预留每cpu 8k的虚存,读写各4k*/

|    FIX_KMAP_BEGIN,  /* 主要用于kmap_atomic*/

|    FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,

#endif

+--------------

|    __end_of_fixed_addresses

|       }

|   FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)

+--------------------------------------------------------------------

|   VMALLOC_END (FIXADDR_START)  (include/asm-i386/pgtable.h)

|       +------------------

|       |  xxxxx: kmap 和 vmalloc 相互重叠,2.6已经修正

|       |     kmap 使用的4M虚存  (asm/highmem.h,LAST_PKMAP)

|       |  PKMAP_BASE (0xfe000000UL) (距离4G 32M)

|       +------------------

|     vmalloc 映射区

|   VMALLOC_START (((unsigned long) high_memory + 2*VMALLOC_OFFSET-1)

|                  & \~(VMALLOC_OFFSET-1)) /*down align 8M */

+--------------------------------------------------------------------

|   约 8M 空洞

+--------------------------------------------------------------------

|   high_memory (见003___arch_i386_mm_ioremap.c 对此的分析)  ..一定映射到内核虚拟空间???,不可以是fixaddr么???

|      内核已经映射了的物理页面 MAX 896M

|

|

|   3G

+--------------------------------------------------------------------

|   resoved for app 0-3G

+--------------------------------------------------------------------

(3) pagetable_init

 static void __init pagetable_init (void)

 {

         unsigned long vaddr;

         pgd_t *pgd_base = swapper_pg_dir;

         /* Enable PSE if available */

         if (cpu_has_pse) {

                 set_in_cr4(X86_CR4_PSE);

         }

         /* Enable PGE if available */

         if (cpu_has_pge) {

                 set_in_cr4(X86_CR4_PGE);

                 __PAGE_KERNEL |= _PAGE_GLOBAL;

                 __PAGE_KERNEL_EXEC |= _PAGE_GLOBAL;

         }

         kernel_physical_mapping_init(pgd_base);

         remap_numa_kva();

         /*

          * Fixed mappings, only the page table structure has to be

          * created - mappings will be set by set_fixmap():

          */

         vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;

         page_table_range_init(vaddr, 0, pgd_base);    //这里用0,应该是超过了4G,或者2^64,回饶,所以是0 

         permanent_kmaps_init(pgd_base);

 }

  /* This maps the physical memory to kernel virtual address space, a total 

  * of max_low_pfn pages, by creating page tables starting from address 

  * PAGE_OFFSET.

  */

 PAGE_OFFSET      0xc0000000

//初始化页目录,页表,,

//1页目录 = 1 * (4k/4) * 4k = 4M,    896M,所以要用掉页目录表中的 896/4 = 225项  

//pse设置话是一页面是4MB了,

//这样

(4) kernel_physical_mapping_init

 static void __init kernel_physical_mapping_init(pgd_t *pgd_base)

 {

         unsigned long pfn;

         pgd_t *pgd;

         pmd_t *pmd;

         pte_t *pte;

         int pgd_idx, pmd_idx, pte_ofs;

         pgd_idx = pgd_index(PAGE_OFFSET);   //内核虚拟地址开始处....

         pgd = pgd_base + pgd_idx;

         pfn = 0;

         for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {

                 pmd = one_md_table_init(pgd);  //This only returns the pgd entry ,即pmd = pgd..

                 if (pfn >= max_low_pfn)

                         continue;

                 for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {

                         unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET;

                         /* Map with big pages if possible, otherwise create normal page tables. */

                         if (cpu_has_pse) {

                         } else {

                                 pte = one_page_table_init(pmd);  //获得页表指针,没有则分配页表.设置pgd,(二级,pmd就是pgd)

                                 for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++) {

                                                 if (is_kernel_text(address))   //是不是内核text

                                                         set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));

                                                 else

                                                         set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));

                                 }

                         }

                 }

         }

 }

  /*

   * Create a page table and place a pointer to it in a middle page

   * directory entry.

   */

  static pte_t * __init one_page_table_init(pmd_t *pmd)

  {

          if (pmd_none(*pmd)) {      //开始时,pmd为none,分配pte_t表...然后建立映射.

                  pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);

                  set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));     //设置页面目录.

                  if (page_table != pte_offset_kernel(pmd, 0))

                          BUG();  

                  return page_table;

          }

          return pte_offset_kernel(pmd, 0);

  }

 #define pte_offset_kernel(dir, address) \

         ((pte_t *) pmd_page_kernel(*(dir)) +  pte_index(address))

 #define pmd_page_kernel(pmd) \

                 ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))

(5) page_table_range_init  ,,,没设置pte...因为这是用来映射高端内存的或者别的用途?.要用的时候再设置pte项..而不是永久映射.

 static void __init page_table_range_init (unsigned long start, unsigned long end, pgd_t *pgd_base)

 {

         pgd_t *pgd;

         pud_t *pud;

         pmd_t *pmd;

         int pgd_idx, pmd_idx;

         unsigned long vaddr;

         vaddr = start;

         pgd_idx = pgd_index(vaddr);

         pmd_idx = pmd_index(vaddr);

         pgd = pgd_base + pgd_idx;

         for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {

                 if (pgd_none(*pgd))               //永远为0..因为pmd总是存在

  /*

   * The "pgd_xxx()" functions here are trivial for a folded two-level

   * setup: the pud is never bad, and a pud always exists (as it's folded

   * into the pgd entry)

   */

  static inline int pgd_none(pgd_t pgd)           { return 0; }

                         one_md_table_init(pgd);    

                 pud = pud_offset(pgd, vaddr);

                 pmd = pmd_offset(pud, vaddr);

                 for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {

                         if (pmd_none(*pmd))               //实际上就是页表为空?

                                 one_page_table_init(pmd); //设置页目录项

                         vaddr += PMD_SIZE;

                 }

                 pmd_idx = 0;

         }

 }

(6)  permanent_kmaps_init  没设置pte...因为这是用来映射高端内存的.要用的时候再设置pte项

/* *为fix KMAP预留每cpu 8k的虚存,读写各4k*/

  /*

   * Ordering is:

   *

   * FIXADDR_TOP

   *                      fixed_addresses

   * FIXADDR_START

   *                      temp fixed addresses

   * FIXADDR_BOOT_START

   *                      Persistent kmap area

   * PKMAP_BASE

   * VMALLOC_END

   *                      Vmalloc area

   * VMALLOC_START

   * high_memory

   */

  #define PKMAP_BASE ( (FIXADDR_BOOT_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK )

 static void __init permanent_kmaps_init(pgd_t *pgd_base)

 {

         pgd_t *pgd;

         pud_t *pud;

         pmd_t *pmd;

         pte_t *pte;

         unsigned long vaddr;

         vaddr = PKMAP_BASE;

         page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);  //还是调用上一个函数.设置好,页目录项

         pgd = swapper_pg_dir + pgd_index(vaddr);

         pud = pud_offset(pgd, vaddr);

         pmd = pmd_offset(pud, vaddr);

         pte = pte_offset_kernel(pmd, vaddr); //返回页表指针. 

         pkmap_page_table = pte; 

 }

  #ifdef CONFIG_X86_PAE

  #define LAST_PKMAP 512

  #else

  #define LAST_PKMAP 1024

  #endif

所以kmap可以分配1024*4k= 4M空间.

(7)  atomic 的高端内存...

 static void __init kmap_init(void)

 {

         unsigned long kmap_vstart;

         /* cache the first kmap pte */

         kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);

         kmap_pte = kmap_get_fixmap_pte(kmap_vstart);

         kmap_prot = PAGE_KERNEL;

 }

(8)vmalloc的区间没有建立映射..

应该vmalloc时建立映射.