memblock_isolate_range

kernel: 5.10
arch: arm64

/**
 * memblock_isolate_range - isolate given range into disjoint memblocks
 * @type: memblock type to isolate range for
 * @base: base of range to isolate
 * @size: size of range to isolate
 * @start_rgn: out parameter for the start of isolated region
 * @end_rgn: out parameter for the end of isolated region
 *
 * Walk @type and ensure that regions don't cross the boundaries defined by
 * [@base, @base + @size).  Crossing regions are split at the boundaries,
 * which may create at most two more regions.  The index of the first
 * region inside the range is returned in *@start_rgn and end in *@end_rgn.
 *
 * Return:
 * 0 on success, -errno on failure.
 */
static int __init_memblock memblock_isolate_range(struct memblock_type *type,
                                        phys_addr_t base, phys_addr_t size,
                                        int *start_rgn, int *end_rgn)
{
        phys_addr_t end = base + memblock_cap_size(base, &size);
        int idx;
        struct memblock_region *rgn;

        *start_rgn = *end_rgn = 0;

        if (!size)
                return 0;

        /* we'll create at most two more regions */
        while (type->cnt + 2 > type->max)
                if (memblock_double_array(type, base, size) < 0)
                        return -ENOMEM;

        for_each_memblock_type(idx, type, rgn) {
                phys_addr_t rbase = rgn->base;
                phys_addr_t rend = rbase + rgn->size;

                if (rbase >= end)
                        break;
                if (rend <= base)
                        continue;

                if (rbase < base) {
                        /*
                         * @rgn intersects from below.  Split and continue
                         * to process the next region - the new top half.
                         */
                        rgn->base = base;
                        rgn->size -= base - rbase;
                        type->total_size -= base - rbase;
                        memblock_insert_region(type, idx, rbase, base - rbase,
                                               memblock_get_region_node(rgn),
                                               rgn->flags);
                } else if (rend > end) {
				/*
                         * @rgn intersects from above.  Split and redo the
                         * current region - the new bottom half.
                         */
                        rgn->base = end;
                        rgn->size -= end - rbase;
                        type->total_size -= end - rbase;
                        memblock_insert_region(type, idx--, rbase, end - rbase,
                                               memblock_get_region_node(rgn),
                                               rgn->flags);
                } else {
                        /* @rgn is fully contained, record it */
                        if (!*end_rgn)
                                *start_rgn = idx;
                        *end_rgn = idx + 1;
                }
        }

        return 0;
}

memblock_isolate_range实际上就是通过遍历memblock_type的所有memblock_region区间,将请求区间(base,size)与memblock_type重叠的memblock_region区间分离出来,如果请求区间跨越两个memblock_region区间的边界,则会创建新的memblock_region区间并插入。最后通过start_rgn 和end_rgn记录分离区间的索引,以供后续操作,当然此时的区间与原有区间可能已经不一样了,它只代表重叠的部分。
这里有一个例子:

from:https://stackoverflow.com/questions/58525960/about-linux-v5-4-kernel-arm64-memblock-init-fdt-enforce-memory-region
As an example think of a memory range 0-10 and 3 memory blocks A[0-3], B[4-8], C[9-10], with crash kernel being on 2-6. In this case memblock_isolate_range() will split A to two blocks A1[0-1] and A2[2-3], and B to B1[4-6] and B2[6-8], and will put the index of A1 on start_rgn and index of B2 on end_rgn. So between start_rgn and end_rgn we’ll get A2[2-3] and B1[4-6] that include the reserved region.

假设有一段内存区域【0,9】,当前已经有三段memblock_region区间,物理地址区间分别为[0,3], [4,8],[9,10], 现在有段请求物理区间地址为[2,6],经过memblock_isolate_range,会划分为[0,2],[2,3],[4,6],[6,8],[9,10]的memblock_region区间,也就是会创建[0,2], [2,3], [4,6], [6,8]几个区间,start_rgn和end_rgn分别记录了重叠区间的起始和结束索引,此处分别为1和3(比实际加1)
从上面的例子可以看出,memblock_isolate_range的目的是为了找到与之前区间有重叠的部分,并为重叠部分新建区间,同时将之前区域分割成与请求区间有重叠的部分和没有重叠的部分,将没有重叠的部分的区间重新插入到内存区域。如上原有区间[0,3], [4,8]与请求区间[2,6]产生重叠,则将其分割为[0,2] [2,3],[4,6],[6,8], 其中原有区间分割出的[0,2],[6,8]重新插入到内存区域,[2,3],[4,6]将作为隔离区间等待处理。
如下通过打印可以看到:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值