自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(110)
  • 收藏
  • 关注

原创 linux之 内存管理(6)-arm64 内核虚拟地址空间变化

内核中划分的这么多区域,且都有自己对应的地址与大小,这些地址和大小在kernel中哪里定义着呢?具体位于:arch/arm64/include/asm/memory.h。.....内核线性映射区的起始地址,大小为128TB。KASAN影子内存的起始虚拟地址,大小为32TB。为什么是32TB呢?因为KASAN通常使用1:8或1:16比例的内存来做影子内存,分别对应大小为256TB/8=32TB或256TB/16=16TB,这里表示的是1:8的情况所以是32TB。

2025-06-09 11:44:45 1112

原创 Linux之 SPI 驱动框架- spi-mem 框架

那么问题来了, 为什么要开发新的 SPI 存储器接口?有了这个新的框架, SPI NOR 和SPI NAND 都可以基于相同的SPI控制器驱动进行支持了。m25p80 驱动将被修改成,使用spi-mem 接口,取代具有局限性的spi_flash_read() 接口。目前, 我们仍然有专用的SPI NOR控制器,但是最终是移除他们,并将他们移植为 drivers/spi/ 下 的普通SPI控制器驱动。

2025-05-23 15:20:58 1173

原创 Linux 之 MTD 子系统框架

接着nand_read函数又会调用struct nand_ecc_ctrl中的read_page函数,而read_page函数又会调用struct nand_chip中read_buf函数,从而真正把NAND芯片中的数据读取到buffer中(所以这个read_buf的意思其实应该是read into buffer,另外,这个buffer是struct mtd_info中的nand_read函数传下来的)。还需注意一点, 在执行dw_spi_write_then_read()前是禁中段和禁抢占的。

2025-05-22 17:13:10 1284 1

原创 linux之 pcie MSI-X中断编程

当前数据中心服务器,CPU基本都是基于PCIE总线和各种设备(例如,内存、显卡和网卡等)相连。而各种PCIE设备采用 MSIX(Message Signaled Interrupt eXtended - 基于消息的信号中断扩展)将中断信号发送给CPU。我们知道MSI最多支持32个中断向量号,而MSI-X中断向量数目最大为2048。那我们编程时如何获取、申请、控制这些中断向量资源呢,本文将为你揭开神秘的面纱。

2025-05-20 14:01:41 1087

原创 linux之 pcie 总线协议基础知识

在读pcie 相关文档时,发现了一篇比较好的文章,在这里摘抄并增加自己实战中的分享和疑问。pcie 的总线架构,每家SOC厂商可能都不相同;下面就展示一下intel 芯片的总线架构,至于自己公司的总线架构是属于保密的,不方便展示:如图 Uncore 和 IOH 组成 PCIe Root Complex。Root Complex 挂接了 PCIe 的 GFX 图像显卡,DDR3 内存,两个 PCIE switch,以及一个 10Gb Ethernet PCIe endpoint。如果通过 lspci -tv

2025-05-15 16:46:47 909

原创 Linux内核之高效缓冲队列kfifo

队列是常见的一种数据结构,简单看来就是一段数据缓存区,可以存储一定量的数据,先存进来的数据会被先取出,First In Fist Out,就是FIFO。FIFO主要用于缓冲速度不匹配的通信。例如生产者(数据产生者)可能在短时间内生成大量数据,导致消费者(数据使用方)无法立即处理完,那么就需要用到队列。生产者可以突然生成大量数据存到队列中,然后就去休息,消费者再有条不紊地将数据一条条取出解析。

2025-04-03 16:25:32 1327

原创 linux之 内存管理(5)-CMA 连续内存管理器

在linux驱动开发过程中经常需要使用到连续大块物理内存,尤其是DMA设备。而实际在系统经过长时间的允许之后,物理内存会出现比较严重的碎片化现象,虽然通过内存规整,内存回收等手动可以清理出一段连续的物理内存,但是并不能保证一定能够申请较大连续物理块。

2025-03-27 14:32:34 871

原创 linux之 内存管理(4)-kernel 启动时 内存 zone 初始化

其中就完成了arm64架构下的memblock的初始化;

2025-03-20 10:30:47 960

原创 linux之 内存管理(3)-kernel 启动时 内存初始化 sparse memory

Uniform-Memory-Access,一致内存访问物理存储器被所有CPU均匀共享。所有处理机对所有存储字具有相同的存取时间。

2025-03-19 20:13:03 987

原创 linux之 内存管理(2)-kernel 启动时 内存初始化 memblock

先 介绍 memblock;

2025-03-19 19:48:12 767

原创 linux之 内存管理(1)-armv8 内核启动页表建立过程

第一、64位地址,四级页表,每个页表4k,就是一个page,能存储512个entry,每个entry 占用8字节,这是最常见的情况。

2025-03-19 14:55:19 1294

原创 SOC-BL32 的optee 启动流程(11)

前面我们已提到optee整体架构包括运行在secure el1和secure el0的optee os,运行在el3的bl31,运行在non secure el1的linux tee driver,以及运行在non secure el0的optee client。

2025-03-10 16:31:12 660

原创 SOC-内核初始化(10)

上一篇我们讨论了内核初始化时异常等级和页表创建相关的一些背景知识,除此之外自然也少不了启动三件套:参数保存、cpu系统寄存器初始化以及c语言运行时环境准备。由于kaslr主要用于增强内核安全性,在启动流程中并不是必须的,因此在本篇我们先不介绍与该特性相关的流程。

2025-03-10 16:13:43 842

原创 SOC-内核启动前的必备知识(9)

 经过漫漫征途终于进入内核大门了,现在内核将愉快地从第一条指令开始执行。但在开始内核之旅前,还是有必要再看下系统进入内核之前的状态。我们知道uboot的最后一步是把内核拷贝到内存,并将cpu设置为如下状态:(1)MMU处于关闭状态(2)dcache处于关闭状态,指令cache可以是关闭或者打开的(3)将dtb的地址存放到x0寄存器中(4)通过armv8_switch_to_el2函数跳转到内核入口地址执行  由于刚进入内核时页表还没有建立,此时系统运行在实模式,且ARM8数据cache的开启需要依赖

2025-03-10 15:51:11 1133 1

原创 SOC-uboot 移植(8)

uboot需要支持众多的硬件,并且具有良好的可扩展性、可移植性和可维护性,因此必须要有一个设计良好的代码架构。代码架构的设计总是与软硬件架构密不可分的,在硬件层面嵌入式系统的核心一般包括以下层次:(1)目标板:它包含了系统运行所需的所有组件,如、各种外设以及时钟源、电源管理芯片等(2)SOC:它包含了cpu、总线控制器、集成在片内的rom、sram、dma控制器、硬件加速器、异构核,以及片内时钟、电源控制模块等。

2025-03-10 14:40:18 673

原创 SOC-uboot 启动流程 四(7)

uboot主要用于启动操作系统,以armv8架构下的linux为例,其启动时需要包含kernel、dtb和rootfs三部分。uboot镜像都是以它们为基础制作的,因此在介绍uboot镜像格式之前我们需要先了解一下它们的构成。

2025-03-10 11:39:45 794

原创 SOC-uboot 启动流程 3(6)

uboot在初始化完成后会为用户提供一个命令行交互接口,用户可通过该接口执行uboot定义的命令,以用于查看系统状态,设置环境变量和系统参数等。为了方便对硬件和驱动的管理,uboot还引入了类似linux内核的设备树和驱动模型特性。当然,为了增加系统的可配置性、可调试性以及可跟踪性等,它还支持环境变量、log管理、bootstage统计以及简单的ftrace等功能。下面我们将对这些特性做一简单的介绍。

2025-03-10 11:15:34 763

原创 SOC-uboot 启动流程 2--spl 启动分析(5)

典型的uboot启动流程通常包含三个阶段,bootrom(或xip)--> spl --> uboot。其中bootrom的特点如下:(1)其存储介质需要具有片上执行能力因为在系统初始化时,cpu只能访问可以直接寻址的存储器,如ROM。而像SPI FLASH或NAND FLASH等外部存储器,都需要相应的驱动才可以访问,故在启动的最初阶段cpu无法访问。因此cpu执行的第一级启动镜像一般都是产商固化在SOC内部存储器(通常为ROM)上的。(2)它的主要功能是加载并执行BL2镜像。

2025-03-07 15:32:21 997

原创 SOC-uboot 启动流程 1(4)

回顾下我们前面介绍的atf,其基本启动流程为:BL1->BL2->BL31->BL32->BL33(uboot),即在bl32启动完成后再启动uboot,uboot作为启动链中作为最后一级镜像,用于启动最终的os。Atf是arm为了增强系统安全性引入,只支持armv7和armv8架构的可信固件。而uboot是通用的嵌入式系统引导程序,其可以支持包含arm在内的多种处理器架构,如mips、riscv、powerpc以及x86等,且其历史比atf更加久远。

2025-03-04 19:56:14 752

原创 Linux rapidio- rio_test_dma 调试代码分析(3)

当前使用的驱动源码来自,驱动源码中包含block DMA的测试应用层工具——rio_test_dma。TSI721在处理block DMA Descriptors时,可以将Descriptors转换成以下4中rapidio操作(参考:《Tsi721 ™ User Manual》P189)rio_test_dma工具是使用的NWRITE_R。本文是在使用rio_test_dma工具进行block DMA测试的驱动流程分析笔记。

2025-03-03 17:23:07 1060

原创 Linux rapidio- tsi721 芯片的doorbell 和message 代码分析(2)

第10类包格式是门铃事务格式。它没有数据载荷。门铃事务的请求包格式如下图所示:上图中Ftype字段固定为10,表示这是一个门铃事务,8位的Reserved字段应该置0,Source TID指的是请求方的事务ID, info(msb)表示的是发送信息的高8位,info(lsb)表示的是发送信息的低8位。如果信息是用数字表示的,而且长度大于8位,那么数据符合低地址存放高字节(big-endian)的格式。比特流中先到达的是高字节。

2025-02-28 17:30:48 813

原创 SOC-ATF 安全启动BL31流程分析(3)

与bl1和bl2不同,bl31包含两部分功能,。在系统启动完成后,,并处理来自其它异常等级的smc异常,以及其它需要路由到EL3处理的中断等。因此bl31启动流程主要包含以下工作:(1)cpu初始化(2)c运行时环境初始化(3)基本硬件初始化,如gic,串口,timer等(4)页表创建和cache使能(5)启动后级镜像的准备以及新镜像的跳转(6)若bl31支持el3中断,则需要初始化中断处理框架(7)运行时不同secure状态的smc处理,以及异常等级切换上下文的初始化。

2025-02-26 18:16:57 971

原创 SOC-ATF 安全启动BL2流程分析(2)

Bl2的启动流程与bl1类似,主要区别是bl2的初始化流程比bl1更简单,但其可能需要加载更多的镜像,如bl31、bl32和bl33。由于bl2可以运行于el3或s-el1,它们的入口函数和处理流程都有所区别,为了简化分析我们选取比较常见的s-el1方式,以下为其总体执行流程:上图仅供参考,实际看一下代码结构:上面截图展示了 链接汇编文件,bl2_el3.ld.S 是指bl2 运行于el3;bl2.ld.S 是实现bl2运行于s-el1 .

2025-02-26 17:37:11 1153

原创 SOC-ATF 安全启动BL1流程分析(1)

这是 ATF 的官方源码仓库,包含最新的代码、文档和示例。

2025-02-26 15:15:39 1155

原创 SOC- armv8 启动流程和安全启动

以atf的BL1 smc处理流程为例,EL1调用者通过smc指令陷入到EL3异常,此后CPU将跳转到EL3异常向量表的vector_entry SynchronousExceptionA64入口处,该函数解析esr_el3寄存器的异常原因,若其为smc异常,就跳转到smc处理函数smc_handler64中。,各家厂商基于这个进行DIY。(5)从前面的镜像启动流程可知,若BL2运行于secure EL1下,当其执行完成后,需要通过smc再次陷入BL1去执行BL31流程,因此BL2和BL1的地址不能有重叠。

2025-02-17 16:41:47 1997

原创 linux之调度管理(13)- wake affine 唤醒特性

select_task_rq_fair 选核其实是一个优选的过程, 通常会有限选择一个 cache-miss 等开销最小的一个根据 wake_affine 选择调度域并确定 new_cpu根据调度域及其调度域参数选择兄弟 idle cpu 根据调度域及其调度域参数选择兄弟 idle cpu根据调度域选择最深idle的cpu根据调度域选择最深idle的cpu find_idest_cpu。

2024-11-26 17:15:13 1139

原创 linux之调度管理(12)- SMP 负载均衡

负载均衡以当前CPU开始,自下而上地遍历调度域,从最底层的调度域开始做负载均衡。允许做负载均衡的首要条件是当前CPU是该调度域中第一个CPU,或者当前CPU是空闲CPU。详见should_we_balance()函数。在调度域中查找最繁忙的调度组,更新调度域和调度组的相关信息,计算出该调度域的不均衡负载值(imbalance)。在最繁忙的调度组中查找最繁忙的CPU,并把最繁忙CPU中的进程迁移到当前CPU上,迁移的负载量为不均衡负载值。

2024-11-25 18:37:12 1002

原创 linux之调度管理(11)-cpu动态调频总体架构

内核中有些子系统,可能需要向该子系统中所有设备动态地添加或移除特定功能。为了支持该特性,内核抽象出了subsys_interface机制,该机制支持动态地向subsys注册或注销一个subsys_interface。其中注册流程如下:源码目录-kernel/drivers/base/bus.cif (!sif ||!if (!它的原理很简单,就是遍历subsys上所有的设备,并分别对它们调用add_dev回调。

2024-11-21 10:42:24 1752

原创 linux之调度管理(9)-SMP cpu hotplug

在单核时代,操作系统只需要管理一个cpu,当系统有任务要执行时,所有任务在该cpu的就绪队列上排队,调度器根据调度算法选择一个最佳任务执行。当就绪队列上的所有任务都执行完成后,cpu就执行idle进程而进入空闲状态。由于idle进程的优先级最低,因此一旦有其它任务进入就绪队列,就又会抢占idle进程继续执行实际的任务。cpu不停地在各个任务以及idle进程之间切换,实现整个系统的运转。

2024-11-19 18:07:21 1194

原创 linux之调度管理(8)-SMP cpu 的 psci启动

psci是arm提供的一套电源管理接口,当前一共包含0.1、0.2和1.0三个版本。它可被用于以下场景:(1)cpu的idle管理(2)cpu hotplug以及secondary cpu启动(3)系统shutdown和reset但该接口不包含dvfs和设备电源管理(如像GPU之类的外设电源管理)功能。由于psci与虚拟化以及trust os有一定的关联,为了专注于电源管理相关的实现,故本系列的介绍都不涉及与它们相关的内容。

2024-11-19 16:52:24 1228

原创 linux之调度管理(7)-SMP cpu 的spin-table启动

soc在启动阶段除了一些特殊情况外(如为了加快启动速度,在bl2阶段通过并行加载方式同时加载bl31、bl32和bl33镜像),一般都没有并行化需求。因此只需要一个cpu执行启动流程即可,这个cpu被称为primary cpu,而其它的cpu则统一被称为secondary cpu。为了防止secondary cpu在启动阶段的执行,它们在启动时必须要被设置为一个特定的状态。  当primary cpu完成操作系统初始化,调度系统开始工作后,就可以通过一定的机制启动secondary cpu。显然second

2024-11-18 18:01:51 1216

原创 linux之调度管理(6)-SMP系统 CPU 定义和初始化

由于内核支持cpu hotplug,因此一个当前正在运行的cpu在其后可能会从系统中被移除,当前被移除的cpu也可能再次被启用,因此cpu可能会在多种状态之间转换。为此内核使用bitmask方式为所有cpu维护了一组状态信息,它们的含义如下:(1)cpu possible:表示系统中可能存在的cpu。它包含了所有从dts中正确解析出来的cpu,如在系统启动时,其设置流程如下:​(2)cpu present:表示当前系统可用的cpu,即cpu已经准备好可以运行了。

2024-11-18 16:34:28 1071

原创 linux之调度管理(5)-实时调度器

rt_rq实时进程运行队列里面提到rt_time和rt_runtime,一个是运行累计时间,一个是最大运行时间,当运行累计时间超过最大运行时间的时候,rt_throttled则被设置为1。

2024-11-15 17:34:19 1405

原创 Linux之调度管理(4)-组调度的带宽控制以及组调度的权重计算

前面几章已经详细介绍了组调度的原因和创建,下面直接上关系说明和关系图。关于组调度的相关数据结构,组织如下:(网友的图很清楚了)

2024-11-13 17:40:43 1067

原创 Linux之调度管理(3)-CFS调度器 详解

普通进程:static_prio=prio=normal_prio;实时进程:prio=normal_prio=99-rt_priority;static_prio保持默认值不改变。

2024-11-13 15:24:18 1263

原创 linux之调度管理(2)-调度器 如何触发运行

因为我们主要讲解的是调度器,而会涉及到一些系统定时器的知识,这里我们简单讲解一下内核中定时器是如何组织,又是如何通过通过定时器实现了调度器的间隔调度。首先我们先看一下内核定时器的框架,具体定时器的详解在其他文章中。在内核中,会使用strut clock_event_device结构描述硬件上的定时器,每个硬件定时器都有其自己的精度,会根据精度每隔一段时间产生一个时钟中断。

2024-11-07 14:32:40 1391

原创 linux之调度管理(1)-调度器的初始化

内核源码路径:kernel/kernel/sched/core.c。

2024-11-06 17:54:43 1240

原创 linux之网络子系统-用户层接收数据包之多路复用方案(epoll)

在上一部分的阻塞模式中(linux之网络子系统-用户层接收数据包之同步阻塞方案-CSDN博客),用户进程为了等待一个socket就得被阻塞掉,如果想要同时为多个用户提供服务要么就得创建对应数量的进程处理,要么就使用非阻塞的方式。进程不说创建,单论上下文切换就需要很大的耗时,而如果非阻塞的模式,就得轮询遍历,会导致CPU空转,并且每次轮询都需要进行一次系统调用,所以Linux提供了多路复用的机制来实现一个进程同时高效地处理多个连接。epoll就是其中最优秀的实现方式,其提供了以下几个相关的函数:在用户进程调用

2024-11-01 16:12:21 1223

原创 linux之网络子系统-用户层接收数据包之同步阻塞方案

我们自己的代码所在的进程:我们调用的socket()函数会进入内核态创建必要的内核对象。recv()函数会在进入内核态以后负责查看接收队列,以及在没有数据可以处理的时候把当前进程组色调,让出CPU。硬中断、软中断上下文:在这些组件中,将包处理完后会放到socket的接收队列中,然后根据socket内核对象找到其等待队列中正在因为等待而被阻塞掉的进程,将它唤醒。每次一个进程专门为了等待一个socket上的数据就被从CPU上拿出来,然后换上另一个进程。

2024-11-01 14:01:08 1184

原创 linux之网络子系统- TCP连接的开销,主要是内存的开销

*NUMA是一种针对多处理器系统的内存架构,其主要思想是将物理内存划分为多个节点,每个处理器可以直接访问所有的内存,但访问不同节点的内存的延迟和带宽可能会有所不同。**在NUMA架构下,**每个CPU会有自己的独立的内存控制器,并且独立连接到一部分内存(直连的这部分内存称为本地内存),组成一个node,不同node之间通过QPI(Quick Path Interconnect)进行通信访问远程内存。这些内存块在物理内存中是连续的,也就是说,它们包含的页框在物理内存中是紧邻的。

2024-11-01 11:23:00 1142

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除