麒麟系统在FT2000+下预留连续物理内存空间

1、背景介绍

项目需要在系统下预留一段连续物理地址空间供FPGA启动DMA直接写入,这样提高读写带宽。目前有两种方式可以实现该需求。

注意:前提是操作系统将内存空间访问权限全部放开,否则无法预留空间。

2、实现方法

方式一:

直接修改grub.cfg,添加memmap参数从内存的物理地址开始预留需要的空间,如下:

上图中圈出来的0xc00000000这段内存地址是BIOS里面配置的,八通道32G的FT2000+内存物理地址分配如下:

	memory@0 {device_type = "memory";reg = <0x000 0x00000000 0x002 0x00000000>;numa-node-id = <0>;};memory@1 {device_type = "memory";reg = <0x002 0x00000000 0x002 0x00000000>;numa-node-id = <1>;};memory@2 {device_type = "memory";reg = <0x004 0x00000000 0x002 0x00000000>;numa-node-id = <2>;};memory@3 {device_type = "memory";reg = <0x006 0x00000000 0x002 0x00000000>;numa-node-id = <3>;};memory@4 {device_type = "memory";reg = <0x008 0x00000000 0x002 0x00000000>;numa-node-id = <4>;};memory@5 {device_type = "memory";reg = <0x00A 0x00000000 0x002 0x00000000>;numa-node-id = <5>;};memory@6 {device_type = "memory";reg = <0x00C 0x00000000 0x002 0x00000000>;numa-node-id = <6>;};memory@7 {device_type = "memory";reg = <0x00E 0x00000000 0x002 0x00000000>;numa-node-id = <7>;};

重启后通过cat /proc/iomem就能查看是否预留成功,成功会有显示

注:下图只是示例,不是预留的0xc00000000这个地址

方式一的优点:在操作系统启动阶段就预留好,每次都能预留成功,方法简单

缺点:这段内存无法被系统识别,应用只能通过devmem方式去使用,无法使用malloc等其他方式分配使用,浪费空间。

方式二:

采用cma方式预留,bios中需要首先预留一段内存空间,并添加一个cma设备,地址、大小都需要指定好

添加设备

这么做的目的就是让cma分配空间时从预留的这段内存中去分配。

然后添加驱动程序,上电加载驱动,代码如下,驱动中可以修改预留大小

#include <linux/types.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/device.h>
#include <asm/io.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/of_gpio.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/spinlock.h>
#include <linux/poll.h>
#include <linux/of_reserved_mem.h>
#include <linux/dma-mapping.h>#define ALLOC_SIZE (2048*1024*1024UL) //分配大小设置dma_addr_t dma_phy_addr = 0;
unsigned int *buffer = NULL;
static struct device *mdev;static int test_dma_probe(struct platform_device *pdev)
{int ret;printk("into test_dma_probe\n");mdev = &pdev->dev;dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));ret = of_reserved_mem_device_init(&pdev->dev);if (ret) {printk("test_dma_probe of_reserved_mem_device_init err: %d\n", ret);return 0;}buffer = dma_alloc_coherent(&pdev->dev, ALLOC_SIZE, &dma_phy_addr, GFP_KERNEL);if (!buffer) {dev_err(&pdev->dev, "dma_alloc_coherent buffer allocation failed\n");return 0;}printk("dma_phy_addr=%llx\n", dma_phy_addr);printk("dma_phy_addr=%p\n", buffer);return 0;
}static const struct of_device_id test_of_match[] = {{ .compatible = "hc,test-dma-driver"},{}
};
MODULE_DEVICE_TABLE(of, test_of_match);static struct platform_driver test_dma_driver = {.driver		= {.name	= "test_dma_mem",.of_match_table = of_match_ptr(test_of_match),},.probe		= test_dma_probe,
};static int __init test_dma_init(void)
{int ret;ret = platform_driver_register(&test_dma_driver);if (ret){pr_info("platform_driver_register fail\n");return 0;}pr_info("platform_driver_register success 0x%x \n",ret);return 0;}static void __exit test_dma_exit(void)
{if (dma_phy_addr) {printk("--free dma mem\n");dma_free_coherent(mdev, ALLOC_SIZE, buffer, dma_phy_addr);}platform_driver_unregister(&test_dma_driver);printk("dma test exit successed\n");
}module_init(test_dma_init);
module_exit(test_dma_exit);MODULE_AUTHOR("test");
MODULE_DESCRIPTION("test dma driver");
MODULE_LICENSE("GPL");

Makefile如下:

# SPDX-License-Identifier: GPL-2.0obj-m	+=test-dma-driver.oKDIR=/lib/modules/$(shell uname -r)/buildall:make -C $(KDIR) M=$(PWD) modulesclean:make -C $(KDIR) M=$(PWD) clean

系统启动后能看到这里是reserved内存空间

驱动加载之后能看到预留成功

方式二的优点:cma方式如果不加载驱动那就不会预留空间,这样就避免内存浪费,虽然无法使用malloc方式访问,但可以用dma方式访问,如下:

 

同时用户可以通过脚本的方式在系统启动后这个阶段来指定哪些设备需要加载驱动,哪些不需要加载驱动,比较灵活,不像方式一那样是系统启动过程中预留,必须要修改启动文件才能修改

缺点:需要在bios的设备树中指定分配的起始地址和大小,如果换了地址就需要更改bios

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1549825.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

适用于vue3中图片全屏展示

App中的代码片段 <style scoped> .container {background: url("./assets/back2.jpg");height: 100%;width: 100%;position: fixed;background-size: 100% 100%; } </style>

单机部署多个 nginx

为方便测试&#xff0c;单机部署多个 nginx&#xff0c;监听不同端口&#xff0c;响应不同页面。以其中一个为例&#xff1a; 1、新建目录&#xff1a; /root/nginx/8571/ /root/nginx/8571/html/ /root/nginx/8571/log/ 2、将文件&#xff1a;/usr/sbin/nginx 拷贝至 /root/n…

Ubuntu系统设置开机自启

在测试国产操作系统&#xff1a;银河麒麟、UOS统信机器的过程中&#xff0c;发现开机不自启&#xff0c;总结以下几种方式实现自启 一.rc.local rc.local脚本是一个Ubuntu开机后自动执行的脚本&#xff0c;可以在脚本内添加行指令&#xff0c;该脚本位于/etc/路径下&#xff…

linux系统的服务器怎么设置上电自启,Linux系统开机自启流程

第一步:POST(Power On Safe Test)加电自检 当按下电源键以后,CPU因为有电流通过便开始对自身、I/O设备、内存等硬件进行检验。那么CPU如何得知这些自检指令?我们知道指令存在于内存当中,寻找内存也需要指令。这看起来似乎是一个“死结”。如何解决呢?在CPU生厂商生产CPU的…

Nginx服务器启停命令

Nginx服务器启停命令 nginx安装好后&#xff0c;维护和更新&#xff0c;经常使用到启动和停止nginx服务。现主要介绍两种方式&#xff1a; 1、nginx服务器的信号控制 nginx中的master 和worker 进程是什么&#xff1f;nginx的工作方式是什么&#xff1f;如何获取进程的PID?信…

REDIS如何开启多个库,而不是增加其实例

(转&#xff1a;)来自运维生存时间: http://www.ttlsa.com/html/4010.html 一台服务器上都快开启200个redis实例了&#xff0c;看着就崩溃了。这么做无非就是想让不同类型的数据属于不同的应用程序而彼此分开。 那么&#xff0c;redis有没有什么方法使不同的应用程序数据彼此分…

IDEA同一个工程启动多个实例

spring cloud 集群中同一个工程需要在多个不同的端口启动多个实例&#xff0c;怎么实现呢 下面我已一个简单的服务提供者、服务消费者、eureka注册中心小Demo说明 &#xff08;之所以一个窗口显示3个项目是因为我先创建了一个空project&#xff0c;之后在空project的基础上ne…

易语言启动线程传递多个类型的数据变量

易语言的启动线程默认是传递一个整数的&#xff0c;在 易语言启动线程传递文本参数中&#xff0c;我们讲解了传递文本参数&#xff0c;今天&#xff0c;我们示范传递多个变量 思路是我们把要传递的变量定义成一个整数型数组&#xff0c;传递的是参数内容的内存地址指针&#xf…

在IDEA启动多个Spring Boot工程实例

对于配置比较多方便保存的则使用下面的方式&#xff1a; 方式一 spring boot允通过命名约定按照一定的格式(application-{profile}.properties)来定义多个配置文件&#xff0c;然后通过在application.properyies通过spring.profiles.active来具体激活一个或者多个配置文件&am…

JMeter压力测试-多线程组并发测试(多场景混合并发)

JMeter压力测试&#xff08;一&#xff09;中设置线程组的线程数&#xff0c;即执行时的并发用户数&#xff0c;适用于单个线程组的并发测试。 如果测试需求出现如下场景&#xff0c;该如何使用JMeter实现压力测试呢&#xff1f;即JMeter如何实现多线程组并发测试&#xff0c;…

Java同时执行多个线程(优雅的进行线程池创建)

欢迎访问我的个人博客:www.ifueen.com 有时候我们会遇到这样的场景&#xff0c;需要通过多线程同时去对某些信息进行处理然后再进行开展后续的业务&#xff0c;这时候就需要用到多线程来同时并发处理这些数据 其实多线程处理的方式有很多&#xff0c;线程池&#xff0c;自定义…

python3-启动多个线程

问题&#xff1a;在for循环里面想同时启动多个线程&#xff0c;但是程序运行过程中产生的是线程一个一个启动&#xff0c;即&#xff1a;启动第一个线程之后主线程等待子线程运行完成之后才启动第二个&#xff0c;代码如下&#xff1a; import threading import time def thre…

【优化】Maven开启多线程构建编译 性能优化

【优化】Maven开启多线程构建编译 性能优化 提高编译的效率 IDEA配置 增加跳过测试代码的编译命令&#xff1a; -Dmaven.test.skiptrue 指明多线程进行编译&#xff1a;-Dmaven.compile.forktrue mvn -T 4 clean install mvn -T 1C clean install 以本机为例 使用记事本打…

HTML总结 2[转]

以下转载和参考自&#xff1a;HTML 表单。 1、表格 可以通过 CSS 设置表格的样式&#xff1a; 如下为将上面table.lamp th,td样式中的padding注释掉&#xff0c;开启table.lamp中的padding的效果&#xff1a; 2、列表 3、表单 表单用于收集用户的输入&#xff0c;如下图所…

因为懒得下载Visual Studio,而使用dotnet-cli这件事

window常用命令: 1.windows清屏指令:CLS 2.创建文件夹: mkdir 3.使用敲过的命令:↑ 或者 ↓(这个方向键) nuget官方地址:https://www.nuget.org/ 一、概述: .NET 命令行接口 (CLI) 工具是用于开发、生成、运行和发布 .NET 应用程序的跨平台工具链。 .NET CLI 附带…

10个非常有用的Python库,你知道几个?

整理&#xff5c;TesterHome 这里给大家介绍10个不是最流行但非常有用的Python库&#xff0c;希望可以提供参考帮助。 PyO3 PyO3是一个Rust库&#xff0c;可以让你在Rust中编写Python模块。它可以利用 Rust 的速度和安全性编写高性能的 Python 模块。 https://github.com/PyO3…

NiN(网络中的网络)

1、NiN与AlexNet的区别 卷积层的输入和输出通常是四维数组&#xff08;样本&#xff0c;通道&#xff0c;高&#xff0c;宽&#xff09;&#xff0c;而全连接层的输入和输出则通常是二维数组&#xff08;样本&#xff0c;特征&#xff09;。如果想在全连接层后再接上卷积层&am…

【网络编程系列】NIO

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…

NIO 应用-网络通信

目录 1. 服务端处理器关注读事件2. 服务端启动类3. 客户端处理器4. 客户端启动类5. 先启动服务端&#xff0c;再启动客户端6. 新建一个服务端处理器&#xff0c;同时关注读事件和写事件7. 启动类8. 先启动服务端&#xff0c;再启动客户端代码下载地址 1. 服务端处理器关注读事件…