自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

aspirestro三水问海的博客

No STreams, neither Rivers nor Oceans.

  • 博客(19)
  • 收藏
  • 关注

原创 3.2.5 宙之CPU的时分复用

点击查看系列文章。

2024-08-23 13:18:57 364

原创 3.2.3 从头初始化到身体

最简单粗暴的办法就是给每个任务分一块地盘,但是任务和任务是有区别的,有的任务贪心,不断malloc,很快就会发现自己的地盘不够用;为了让进程听话,内核身先士卒,自身也不能搞特殊化,也得活在虚拟内存空间中,只不过内核算是既得利益者,它独占了一大片的物理内存页面。进程访问虚拟内存的某个地址时,这个地址总是属于一个虚拟页面,映射表能完成从虚拟页面到物理页面的查找,这样虚拟转成了现实。它欺骗进程,告诉它你有一块超大的内存空间可以用,并且已经帮你切分成一个一个大小一致的小块(即页面,一般是4KB),方便取用。

2024-08-22 22:51:22 464

原创 3.2 内核初始化(盘古开天地)

宙者,古往今来,时间为宙。盘古作为0号进程,在head.S汇编代码中,沿着_head(头)->stext(身)->__primary_switch(MMU)->__primary_switched(进程)完成了上述4个步骤,之后就可以跳转到C语言函数start_kernel开始开天辟地。Linux内核的初始化是从0开始的,Documentation/arm64/booting.txt里面写明了,此时中断是完全关闭的,一切似乎都是静止的。所以,只要在源码中定义了.head.text段,就会链接到_text。

2024-08-22 22:49:09 809

原创 3.1 I-pipe四行启动代码

Linux内核的初始化流程是什么样的?是怎么走到start_kernel的?为什么I-pipe选择在start_kernel中进行初始化?四行代码的位置有什么学问?I-pipe的启动代码位于init/main.c: start_kernel函数中。越是简单的代码,背后的故事越多!下一章节,展开这个故事。

2024-08-22 22:41:57 82

原创 2.5.4 对CONFIG_PREEMPT的处理

为保证Linux内核在以上情况下不会被抢占,抢占式内核使用了一个变量preempt_ count,称为内核抢占锁。第14~24行,第9行关闭了虚拟中断,而后在第11行执行preempt_schedule_irq期间,虚拟中断又经历了打开、关闭的过程。对于抢占式内核而言,即便是从中断上下文返回内核空间的进程上下文,只要内核代码不在临界区内,就可以发生抢占,让最高优先级的任务调度执行。第10~12行,在打开硬件中断的情况下,调用preempt_schedule_irq,之后再关闭硬件中断。

2024-08-16 21:44:02 630

原创 2.5 el1_irq

因此,kernel_entry 1保存struct pg_regs的位置,并不是进程内核栈的栈底位置,而是根据实际情况,在进程内核栈中间的某个位置。第18行,在kernel_ventry中,SP_EL1减去了#S_FRAME_SIZE。第2~10行,是对kernel_entry 1的第20~25行的反向操作,还原tast_struct.thread_info.addr_limit的值。第32行,内核栈指针sp_el1弹出,向上走#S_FRAME_SIZE,与kernel_entry压栈的大小一致。

2024-08-16 21:31:23 921

原创 2.4 el0_sync

首先读取ESR_EL1寄存器,向右移位ESR_ELx_EC_SHIFT(26)得到异常发生的原因(Bit 31~26),然后跳转到相应的分支继续处理。根据注释,它代表进程运行在HEAD域。第6行,如果TSK_TI_IPIPE中没有设置_TIP_HEAD标记,第14行tst指令(相当于ands)结果为0,则Z标志位为1,b.eq判断条件成立。第7行,如果TSK_TI_IPIPE中设置_了TIP_HEAD标记,第14行tst指令(相当于ands)结果为1,则Z标志位为0,b.eq判断条件不成立。

2024-08-14 21:20:06 521

原创 2.3.6 返回用户空间

2.3.6.1 概要当el0_irq发生时,被中断的用户态任务有三种类型:任务类型说明1Linux进程,运行在root域。2Xenomai进程,已经迁移到root域即作为Linux进程进行调度3Xenomai进程,在head域运行。综合上一章节中断发生的场景,可能出现的组合如下表。接下来按照场景进行分析。场景/任务类型返回值位于root域,虚拟中断打开1可能可能不可能位于root域,虚拟中断屏蔽0可能可能不可能位于head域0不可能不可能可能。

2024-08-13 22:32:16 989

原创 2.3.5 irq_handler

新增的handle_arch_irq_pipelined除了调用原先的handle_arch_irq之外,就是改变了irq_handler的返回值。根据返回值的不同,el0_irq后续的代码走向是不同的,后面章节会相信分析,这里重点分析handle_arch_irq。如果打开了CONFIG_IPIPE配置项,那么函数调用顺序irq_handler->handle_arch_irq变成了irq_handler->handle_arch_irq_pipelined->handle_arch_irq。

2024-08-12 21:46:20 1062

原创 1.3 拉取I-pipe代码

所以,这个思路是把upstream的修改,不断合并到ipipe自己的分支ipipe/4.19.y-cip。根据上面的分析,ipipe-core-4.19.209-cip59-arm64-12.patch是哪两个分支或commit diff出来的呢?经过对比,是第(5)步和第(2)步的git diff的结果。也可以直接从I-pipe的git代码仓库,直接拉取代码,切换到对应的tag。可以下载I-pipe的patch,通过git apply到kernel.org的Linux内核。,能看到最原始的修改。

2024-08-06 22:04:14 900

原创 1.2 I-pipe基本概念

Head Stage是一个独立的高优先级执行阶段,一旦收到中断,立刻调用out-of-band中断处理程序,丝毫不会被Root Stage中的In-band代码影响。当根域的虚拟中断标志处于打开状态,从头域传递过来的中断可以立即被in-band中断处理程序处理。为了保证头域中的out-of-band代码的实时性,根域中的in-band代码一定不能关闭CPU的物理中断。既要保证头域中的out-of-band中断处理程序随时响应物理中断,又要保证根域中的in-band中断处理程序仅仅在根域能接收中断时执行。

2024-08-06 19:44:18 924

原创 1.1 I-pipe与Xenomai

但是RTAI更新速度比较慢,最新的版本是2021/5/19发布的RTAI 5.3,适配Linux 4.19,主页上宣称支持的硬件是x86和x86_64,对ARM的支持处于rework中。Xenomai2目前已经EOL,Xenomai4比较新,而Xenomai3比较稳定,处于长期维护中,应该是当前使用比较广泛的版本。这里重点学习Xenomai3.2.1版本。第二种,采用双内核的办法,在硬件之上运行一个实时内核,把Linux内核当成的实时内核的一个普通的进程,其代表有RTLinux、RTAI和Xenomai。

2024-08-01 12:11:28 776

原创 2.3.4 trace_hardirqs_off与trace_hardirqs_on

如果打开内核配置项CONFIG_TRACE_IRQFLAGS,那么在硬件中断关闭和打开的过程中,通过调用trace_hardirqs_off/trace_hardirqs_on函数可以记录硬件中断关闭和打开的事件。两个函数调用的tracer_hardirqs_off/tracer_hardirqs_off,服务于ftrace的众多tracer之一irqsoff(CONFIG_IRQSOFF_TRACER)。ipipe_root_p) //如果是非root域,直接return。

2024-07-30 21:54:04 798

原创 2.3.3 el0_irq_naked与enable_da_f

enable_da_f由commit b282e1ce29 arm64: entry.S: convert elX_irq引入,在comments里面写明,在处理IRQ中断时,应该使能调试异常Debug和SError,同时顺便打开了FIQ。el0_irq_naked只有在el0_irq_compat中才调用。此时因为已经调用了kernel_entry 0,32进行了用户态现场保存,因此必须避免重复调用el0_irq中已经调用的kernel_entry 0,直接跳转到标签el0_irq_naked。

2024-07-30 21:03:07 195

原创 2.3.2 kernel_entry 0 与kernel_exit 0

因为从用户栈切到内核栈,因此对于内核栈来说,不存在上一个caller的栈帧,所以pt_regs中定义的u64 stackframe[2]代表的FP/LR的值都设置为0.栈空间是在kernel_ventry中按照struct pt_regs的大小预留好的,所以相当于压入struct pt_regs的reg[0]~reg[29]。第24行,将elr_el1存入X22。第 31行,将X22和X23压栈,就是将elr_el1和spsr_el1的值压入struct pt_regs的pc变量和pstate变量。

2024-07-30 14:37:55 842

原创 2.3.1 el0_irq代码框架

首先沿着vectors->kernel_ventry 0,irq ->el0_irq分析。I-pipe的主要修改点如图中红色字体所示。接下来会对el0_irq中的每一行展开分析。当el0_irq发生时,被中断的用户态进程有两种:一种是Linux进程,一种是迁移到Linux的Xenomai进程。

2024-07-30 11:28:25 190

原创 2.2 ARM64异常处理

异常级别EL0不处理任何异常,必须在更高的异常级别中处理。不同的异常级别有各自独立的VBAR,例如VBAR_EL1,VBAR_EL2,VBAR_EL3等。在异常级别变化的时候,根据是否使用SP0,异常向量表中的表项不同。Linux的运行只涉及EL0和EL1,即Linux内核运行在异常级别EL1,应用程序运行在异常级别EL0. 在EL0或EL1中发生的异常,都会跳转到EL1的异常向量表,根据异常的类别,找到对应的表项。异常级别分为4级,其中EL0不处理异常。当EL0发生异常时,会进入更高的异常级别进行处理。

2024-07-30 10:49:09 1002

原创 Interrupt Pipeline系列文章大纲

1 I-pipe介绍2 I-pipe对ARM64异常向量表的改造2.1 ARM64中断机制http://t.csdnimg.cn/FwMas2.2 ARM64异常处理2.3 el0_irq2.4 el0_sync2.5 el1_irq2.6 el0_sync

2024-07-30 10:43:20 406

原创 2.1 ARM64中断机制

CPU收到一个中断号n后,会去中断描述表IDT(Interrupt Descriptor Table)中,找到第n个中断描述符,从中断描述符中找到中断处理程序。中断信号通常被分为同步中断和异步中断两大类。异步异常发生时,处理器正在处理的指令和异常是完全没有关系的,它们之间没有依赖关系,常见的异步异常包括物理中断和虚拟中断。ARM64的中断机制的顶层概念是异常,同步中断和异步中断被分别称为同步异常和异步异常两种。在不同的CPU架构中,对于中断机制的设计与实现不同,对中断信号的概念划分也有所不同。

2024-07-29 23:59:39 785

Adaptive Domain Environment for Operating Systems

Adaptive Domain Environment for Operating Systems

2024-08-01

Fast Interrupt Priority Management in OS Kernels

Fast Interrupt Priority Management in OS Kernels

2024-08-01

空空如也

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

TA关注的人

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