Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[components][mm]添加预留内存支持 #8025

Merged
merged 1 commit into from
Oct 14, 2023

Conversation

zmshahaha
Copy link
Contributor

@zmshahaha zmshahaha commented Sep 11, 2023

拉取/合并请求描述:(PR description)

[

为什么提交这份PR (why to submit this PR)

目前的系统确定可分配内存的方式是各bsp下定义page_region,然后将其加入伙伴系统的方式。这种做法较为过时,如果通过解析设备树来划分可用内存区域,则更加高效,不用再在各bsp下定义可用区域相关的宏。

该方法需要用到当前尚未实现的预留内存概念,即申请一部分区域作为对设备、内核代码、内核堆栈的预留空间。本pr就是对预留内存的实现。

你的解决方案是什么 (what is your solution)

借用了linux中的memblock概念,在初始化阶段通过设备树获得全部物理内存和预留内存范围,初始化结束时将在全部物理内存但不在预留物理内存的区域释放到伙伴系统中

在什么测试环境下测试通过 (what is the test environment)

在单元测试中加入对memblock的测试,关注了获得的物理内存信息的各种情况,测试用例全部通过。
对a1000设备树进行测试,其对内存区域解析完全正确

]

当前拉取/合并请求的状态 Intent for your PR

必须选择一项 Choose one (Mandatory):

  • 本拉取/合并请求是一个草稿版本 This PR is for a code-review and is intended to get feedback
  • 本拉取/合并请求是一个成熟版本 This PR is mature, and ready to be integrated into the repo

代码质量 Code Quality:

我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:

  • 已经仔细查看过代码改动的对比 Already check the difference between PR and old code
  • 代码风格正确,包括缩进空格,命名及其他风格 Style guide is adhered to, including spacing, naming and other styles
  • 没有垃圾代码,代码尽量精简,不包含#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up
  • 所有变更均有原因及合理的,并且不会影响到其他软件组件代码或BSP All modifications are justified and not affect other components or BSP
  • 对难懂代码均提供对应的注释 I've commented appropriately where code is tricky
  • 代码是高质量的 Code in this PR is of high quality
  • 已经使用formatting 等源码格式化工具确保格式符合RT-Thread代码规范 This PR complies with RT-Thread code specification

@BernardXiong
Copy link
Member

请规范好代码

Copy link
Member

@BernardXiong BernardXiong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码应该是精雕细琢的

components/mm/mm_memblock.h Outdated Show resolved Hide resolved
components/mm/mm_memblock.h Outdated Show resolved Hide resolved
components/mm/mm_memblock.c Outdated Show resolved Hide resolved
components/mm/mm_memblock.c Outdated Show resolved Hide resolved
components/mm/mm_memblock.c Outdated Show resolved Hide resolved
@BernardXiong BernardXiong added -1 No vote v5.1.0 version 5.1.0 (planned to be released by the end of 2023) and removed v5.0.2 labels Sep 23, 2023
@BernardXiong
Copy link
Member

写了个寂寞啊

memblock_desc.vaddr_start = RT_ALIGN_DOWN(reg->memreg.start - PV_OFFSET, ARCH_PAGE_SIZE);
memblock_desc.vaddr_end = RT_ALIGN_DOWN(reg->memreg.end - PV_OFFSET, ARCH_PAGE_SIZE) - 1;

rt_hw_mmu_setup(&rt_kernel_space, &memblock_desc, 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个 API 是非幂等的

Copy link
Contributor Author

@zmshahaha zmshahaha Sep 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我看这个里面的ktbl_set和pagecleanup是幂等的呀?那就改成第一次rt_hw_mmu_setup后续rt_hw_mmu_map行吧。主要这里没法提前知道多少内存区域

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

实现可以,但是这个 API 的语义不是。针对这个语义,其它的架构完全可以实现成 init 类型的,甚至后续迭代也可能变化。要考虑一下通用性。

然后,这么实现初始化流程效率会被拖慢。每一次 rt_hw_mmu_setup 代价是很大的。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

那就改成第一次rt_hw_mmu_setup后续rt_hw_mmu_map行吧

不要直接用 rt_hw_mmu_map 这个 API,内存映射使用 aspace 的 API

Copy link
Contributor Author

@zmshahaha zmshahaha Sep 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

之后这块我打算在rt_memblock_setup_memory_env中调用libcpu中的rt_hw_mmu_setup。然后添加新选项RT_USING_MEMBLOCK,libcpu中的rt_hw_mmu_setup分开和不开这个选项两种情况实现(一个使用mem_desc另一个是memblock)。

主要考虑的是①mmu_setup具体操作与cpu有关,而映射区域信息在memblock里②使用memblock时内存初始化工作尽可能交给rt_memblock_setup_memory_env

由于之后打算修改更多特性(如堆初始化),打算这个特性之后新提pr,这次提交暂时把memblock中初始化映射删掉

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

后续应该是把旧的 mem_desc 给废弃掉。

@BernardXiong
Copy link
Member

之后测试用例的话是要涉及到内部实现的,我想法是测试用例utest里创建个软链接到mm_memblock.c,然后测试用例包含该文件

包含.c文件,这个不是好的模式的。测试相关,先阶段还是多考虑到外部API的测试。内部一个个函数测试,就有些类似单元测试了。是否可以从外部构造测试用例,尽可能测试到内部完整过程

@zmshahaha zmshahaha closed this Sep 26, 2023
@zmshahaha zmshahaha reopened this Sep 26, 2023
@zmshahaha
Copy link
Contributor Author

外部构造测试用例,尽可能测试到内部完整过程

这个破坏之前说的封装性了吧?

主要是预留内存相关只在初始化时用,这个场景不需要了解内部过程,api也不会给出内部信息。测试不算预留内存正常使用的场景。我现在换个方法,memblock.c定义测试需要函数,只在测试宏打开时编译。这个api不放在memblock.h中,只在测试文件开头声明。

@polarvid
Copy link
Contributor

外部构造测试用例,尽可能测试到内部完整过程

这个破坏之前说的封装性了吧?

主要是预留内存相关只在初始化时用,这个场景不需要了解内部过程,api也不会给出内部信息。测试不算预留内存正常使用的场景。我现在换个方法,memblock.c定义测试需要函数,只在测试宏打开时编译。这个api不放在memblock.h中,只在测试文件开头声明。

可以看看是什么原因导致测试不便,从另一个角度推敲内部的设计是否合理。

@zmshahaha
Copy link
Contributor Author

外部构造测试用例,尽可能测试到内部完整过程

这个破坏之前说的封装性了吧?
主要是预留内存相关只在初始化时用,这个场景不需要了解内部过程,api也不会给出内部信息。测试不算预留内存正常使用的场景。我现在换个方法,memblock.c定义测试需要函数,只在测试宏打开时编译。这个api不放在memblock.h中,只在测试文件开头声明。

可以看看是什么原因导致测试不便,从另一个角度推敲内部的设计是否合理。

个人认为主要就是使用场景矛盾问题吧。由于使用场景相对简单,正常使用不会用到内部的数据结构,包括rt_memblock,rt_mmblk_reg,所以提供api时这些数据结构都会封装掉。但测试时又绕不开这些信息。

@polarvid
Copy link
Contributor

polarvid commented Sep 26, 2023

外部构造测试用例,尽可能测试到内部完整过程

这个破坏之前说的封装性了吧?
主要是预留内存相关只在初始化时用,这个场景不需要了解内部过程,api也不会给出内部信息。测试不算预留内存正常使用的场景。我现在换个方法,memblock.c定义测试需要函数,只在测试宏打开时编译。这个api不放在memblock.h中,只在测试文件开头声明。

可以看看是什么原因导致测试不便,从另一个角度推敲内部的设计是否合理。

个人认为主要就是使用场景矛盾问题吧。由于使用场景相对简单,正常使用不会用到内部的数据结构,包括rt_memblock,rt_mmblk_reg,所以提供api时这些数据结构都会封装掉。但测试时又绕不开这些信息。

我理解是 rt_memblock,rt_mmblk_reg 从测试的角度应该是不用考虑的。因为这些数据集本质是由 API 传入的数据构造的。按照这个理解,是否是直接构造 API 的数据就好了?

@polarvid
Copy link
Contributor

外部构造测试用例,尽可能测试到内部完整过程

这个破坏之前说的封装性了吧?
主要是预留内存相关只在初始化时用,这个场景不需要了解内部过程,api也不会给出内部信息。测试不算预留内存正常使用的场景。我现在换个方法,memblock.c定义测试需要函数,只在测试宏打开时编译。这个api不放在memblock.h中,只在测试文件开头声明。

可以看看是什么原因导致测试不便,从另一个角度推敲内部的设计是否合理。

个人认为主要就是使用场景矛盾问题吧。由于使用场景相对简单,正常使用不会用到内部的数据结构,包括rt_memblock,rt_mmblk_reg,所以提供api时这些数据结构都会封装掉。但测试时又绕不开这些信息。

我理解是 rt_memblock,rt_mmblk_reg 从测试的角度应该是不用考虑的。因为这些数据集本质是由 API 传入的数据构造的。按照这个理解,是否是直接构造 API 的数据就好了?

但如果不检查rt_memblock的信息没办法知道api执行的正确性

还有问题就是正常情况下memblock也就初始化用,之后就不用了,所以我也没必要给重置memblock的api,但测试前应该是需要重置memblock在初始状态的。

懂你意思了。

关于第一个,个人感觉可以加一个 API 去 get memblock。因为至少测试有这个需求。

关于第二个,有了 get,清空应该是可行的

@BernardXiong
Copy link
Member

@polarvid 你 approve 后合并吧。等你们的沟通了~~

@CLAassistant
Copy link

CLAassistant commented Sep 27, 2023

CLA assistant check
All committers have signed the CLA.

@zmshahaha
Copy link
Contributor Author

zmshahaha commented Sep 27, 2023

@polarvid 之前提的改了下,加了测试用例,另外错误处理由之前直接halt改为返回RT_EINVAL

然后memblock.c里还是保留了一点只针对测试的接口,主要是测试page初始化能否找到正确区域(memory-reserved)的api。

* @param end the size of the physical address range
* @param flags the flags of the region
*/
rt_err_t rt_memblock_add_memory(char *name, rt_size_t start, rt_size_t end, mmblk_flag_t flags);
Copy link
Contributor

@polarvid polarvid Sep 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感觉 rt_memblock_add_memory 和 rt_memblock_reserve_memory 可以做成一个 API,用 flag 来区分。因为 fdt 那边也是通过 region 属性来区分的。这里的 reserve memory 实际操作是 add reserved memory,算是 add memory 变体。那以后万一再有第三个需求,add DMA pool,照现在这样还要再拷贝一份 API 出来。

Copy link
Contributor Author

@zmshahaha zmshahaha Sep 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这俩是对外的,对用户来说这两个差距比较大吧,这样写感觉用户更清楚是在加啥内存,fdt那边不是通过/memory和/reserved-memory区分吗?

拷贝api我觉得问题倒不大,毕竟这个函数基本不占啥空间,汇编上大概也就是个跳转指令。

然后你例子里这个dma-pool也属于预留内存吧,只是交给dma管理框架来管理。/reserved-memory里面经常有compatible="shared-dma-pool"的子结点

Copy link
Contributor

@polarvid polarvid Sep 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我的例子不够好吧。但意思是 flag 应对变化的需求会更灵活一点。不过这个只是实现的选择,我保持中性的态度。

@BernardXiong BernardXiong added +1 Agree +1 and removed -1 No vote labels Sep 28, 2023
@BernardXiong
Copy link
Member

Please resolve conflicting file:

components/Kconfig

@BernardXiong
Copy link
Member

rebase或者-f推下吧,把中间的修改都合并起来。

@zmshahaha
Copy link
Contributor Author

已合并修改

@BernardXiong BernardXiong merged commit a39da9c into RT-Thread:master Oct 14, 2023
37 checks passed
bettermultiply pushed a commit to bettermultiply/rt-thread that referenced this pull request Oct 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v5.1.0 version 5.1.0 (planned to be released by the end of 2023) +1 Agree +1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants