1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| -+ vmalloc(unsigned long size) \ -+ __vmalloc_node(size, align:1, GFP_KERNEL) \ -+ __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END,...) \ -+ area = __get_vm_area_node(real_size, align, shift, VM_ALLOC | VM_UNINITIALIZED | vm_flags, start, end, node, \ - struct vm_struct *area = kzalloc_node(sizeof(*area), gfp_mask & GFP_RECLAIM_MASK, node); | -+ struct vmap_area *va = alloc_vmap_area(size, align, start, end, node, gfp_mask, 0); "在 vmalloc 整个空间中查找一块合适的没有使用的空间 hole" "查找的地址从 VMALLOC_START 开始, 首先从 vmap_area_root 红黑数上查找, 该树上存放着正在使用的 vmalloc 区块” “从 VMALOC_START 开始, 查找每个存在的vmalloc 区块的hole能够容纳目前要分配的大小。 如果找到了合适的hole, 调用 __insert_vmap_area 把这个 hole 注册到该红黑树中, 如果没找到hole, 则从最后一个 vmalloc 区块的结束地址开始一个新的 vmalloc 区块" | -+ setup_vmalloc_vm(area, va, flags, caller); "将该找到的 va 填充到 vm area 中" | -+ __vmalloc_area_node(area, gfp_mask, prot, shift, node); \ - area->pages = kmalloc_node(array_size, nested_gfp, node); "分配 area->pages 二维数组指针" | - area->nr_pages = vm_area_alloc_pages(gfp_mask | __GFP_NOWARN, node, page_order, nr_small_pages, area->pages); "使用 alloc_page 分配物理页面, 并使用 area->pages 保存这些 page的指针" | -+ vmap_pages_range(addr, addr + size, prot, area->pages, page_shift); "建立页面映射" \ -+ vmap_pages_range_noflush(addr, end, prot, pages, page_shift); \ -+ __vmap_pages_range_noflush(addr, end, prot, pages, page_shift); \ -+ for i in npages: \ -+ vmap_range_noflush(addr, addr + (1UL << page_shift), page_to_phys(pages[i]), prot, page_shift); "为每个 pte 建立映射" "pgd-> p4d -> pud -> pmd -> pte" \ - pgd = pgd_offset_k(addr); "从 init_mm 中获取 指向 pgd 页面目录项的基址, 然后通过addr 找到对应的pgd 表项" | -+ flush_cache_vmap(addr, end); "按地址 刷新tlb" \ -+ flush_tlb_kernel_range(start, end) \ -+ __flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long size, unsigned long stride) \ - "sfence.vma ..."
|