1. memblock_alloc分配内存
memblock数据结构初始化结束,memblock_alloc是内核分配内存的主要工具。memblock_alloc的这种核心地位将持续到buddy system的建立。
793 phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
794 {
795 return memblock_alloc_base_nid(size, align, max_addr, MAX_NUMNODES);
796 }
797
798 phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
799 {
800 phys_addr_t alloc;
801
802 alloc = __memblock_alloc_base(size, align, max_addr);
803
804 if (alloc == 0)
805 panic("ERROR: Failed to allocate 0x%llx bytes below 0x%llx.\n",
806 (unsigned long long) size, (unsigned long long) max_addr);
807
808 return alloc;
809 }
810
811 phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align)
812 {
813 return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
814 }
769 static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
770 phys_addr_t align, phys_addr_t max_addr,
771 int nid)
772 {
773 phys_addr_t found;
774
775 if (WARN_ON(!align))
776 align = __alignof__(long long);
777
778 /* align @size to avoid excessive fragmentation on reserved array */
779 size = round_up(size, align);
780
781 found = memblock_find_in_range_node(0, max_addr, size, align, nid);
782 if (found && !memblock_reserve(found, size))
783 return found;
784
785 return 0;
786 }
98 phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t start,
99 phys_addr_t end, phys_addr_t size,
100 phys_addr_t align, int nid)
101 {
102 phys_addr_t this_start, this_end, cand;
103 u64 i;
104
105 /* pump up @end */
106 if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
107 end = memblock.current_limit;
108
109 /* avoid allocating the first page */
110 start = max_t(phys_addr_t, start, PAGE_SIZE);
111 end = max(start, end);
112
113 for_each_free_mem_range_reverse(i, nid, &this_start, &this_end, NULL) {
114 this_start = clamp(this_start, start, end);
115 this_end = clamp(this_end, start, end);
116
117 if (this_end < size)
118 continue;
119
120 cand = round_down(this_end - size, align);
121 if (cand >= this_start)
122 return cand;
123 }
124 return 0;
125 }
#define for_each_free_mem_range_reverse(i, nid, p_start, p_end, p_nid) \
for (i = (u64)ULLONG_MAX, \
__next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid); \
i != (u64)ULLONG_MAX; \
__next_free_mem_range_rev(&i, nid, p_start, p_end, p_nid))
652 void __init_memblock __next_free_mem_range_rev(u64 *idx, int nid,
653 phys_addr_t *out_start,
654 phys_addr_t *out_end, int *out_nid)
655 {
656 struct memblock_type *mem = &memblock.memory;
657 struct memblock_type *rsv = &memblock.reserved;
658 int mi = *idx & 0xffffffff;
659 int ri = *idx >> 32;
660
661 if (*idx == (u64)ULLONG_MAX) {
662 mi = mem->cnt - 1;
663 ri = rsv->cnt;
664 }
665
666 for ( ; mi >= 0; mi--) {
667 struct memblock_region *m = &mem->regions[mi];
668 phys_addr_t m_start = m->base;
669 phys_addr_t m_end = m->base + m->size;
670
671 /* only memory regions are associated with nodes, check it */
672 if (nid != MAX_NUMNODES && nid != memblock_get_region_node(m))
673 continue;
674
675 /* scan areas before each reservation for intersection */
676 for ( ; ri >= 0; ri--) {
677 struct memblock_region *r = &rsv->regions[ri];
678 phys_addr_t r_start = ri ? r[-1].base + r[-1].size : 0;
679 phys_addr_t r_end = ri < rsv->cnt ? r->base : ULLONG_MAX;
680
681 /* if ri advanced past mi, break out to advance mi */
682 if (r_end <= m_start)
683 break;
684 /* if the two regions intersect, we're done */
685 if (m_end > r_start) {
686 if (out_start)
687 *out_start = max(m_start, r_start);
688 if (out_end)
689 *out_end = min(m_end, r_end);
690 if (out_nid)
691 *out_nid = memblock_get_region_node(m);
692
693 if (m_start >= r_start)
694 mi--;
695 else
696 ri--;
697 *idx = (u32)mi | (u64)ri << 32;
698 return;
699 }
700 }
701 }
702
703 *idx = ULLONG_MAX;
704 }
以上为memblock查找内存空间的过程,通过memblock_reserve标志内存已经使用。
2 memblock_reserve
554 int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
555 {
556 struct memblock_type *_rgn = &memblock.reserved;
557
558 memblock_dbg("memblock_reserve: [%#016llx-%#016llx] %pF\n",
559 (unsigned long long)base,
560 (unsigned long long)base + size,
561 (void *)_RET_IP_);
562
563 return memblock_add_region(_rgn, base, size, MAX_NUMNODES);
564 }
565
把一段内存放入memblock.reserved内。
563行,在上一文章内有提及。
3. memblock_free
memblock_free比较简单,这里就不再摘录了。