
linux内核
文章平均质量分 54
天麓
很懒的码农
展开
-
慢慢欣赏arm64内核启动30 __primary_switched之第三部分
将 x21 的值存放在 __fdt_pointer。而 __fdt_pointer 的定义如下。第1行涉及宏定义 str_l,其定义如下。原创 2024-10-17 09:06:22 · 483 阅读 · 0 评论 -
慢慢欣赏arm64内核启动29 __primary_switched之第二部分
展示代码 adr_l x8, vectors // load VBAR_EL1 with virtual msr vbar_el1, x8 // vector table address isb stp xzr, x30, [sp, #-16]! mov x29, sp#ifdef CONFIG_SHADOW_CALL_STACK adr_l scs_sp, init_shadow_call_stack // Set shadow call stack#endif分析代码原创 2024-10-16 09:10:47 · 247 阅读 · 0 评论 -
慢慢欣赏arm64内核启动28 __primary_switched之第一部分
第1行到第5行是注释,提示这段代码是在使能 MMU 之后执行。入参是 x0,即 __PHYS_OFFSET。第7行将 init_thread_union 的页面物理地址存放在 x4。原创 2024-10-14 09:01:03 · 887 阅读 · 0 评论 -
慢慢欣赏arm64内核启动27 primary_entry之__primary_switch代码第三部分
该宏定义在《慢慢欣赏arm64内核启动10 primary_entry之set_cpu_boot_mode_flag》和《慢慢欣赏arm64内核启动18 primary_entry之__create_page_tables代码第五部分》有介绍。在 ARM64 架构中,页面大小通常是 4KB,所以这个指令实际上是获取 __PHYS_OFFSET 地址所在的 4KB 页面的起始地址。这样我们到了第34行,第34行将 __primary_switched 的内核链接地址存放在了 x8。原创 2024-10-12 09:24:58 · 262 阅读 · 0 评论 -
慢慢欣赏arm64内核启动26 primary_entry之__primary_switch代码第二部分 __enable_mmu
x1 是 TTBR1_EL1 的赋值,《慢慢欣赏arm64内核启动25 primary_entry之__primary_switch代码第一部分》里面有描述。x0 是 SCTLR_EL1 的赋值,《慢慢欣赏arm64内核启动24 primary_entry之__cpu_setup代码第六部分》里面有描述。该函数的作用是使能 MMU,前期做了那么多的工作,就是为了这一刻。该函数需要两个入参,x0 和 x1。第1行到第12行是注释。原创 2024-10-08 09:03:38 · 564 阅读 · 0 评论 -
慢慢欣赏arm64内核启动24 primary_entry之__cpu_setup代码第六部分
第1行到第3行是注释,准备寄存器 SCTLR,SCTLR 是什么东东我们继续分析。第4行涉及宏定义 SCTLR_EL1_SET,定义如下。原创 2024-09-26 09:07:32 · 972 阅读 · 0 评论 -
慢慢欣赏arm64内核启动23 primary_entry之__cpu_setup代码第五部分
CONFIG_ARM64_HW_AFDBM 是 Linux 内核的一个配置选项,用于启用 ARMv8.1 架构扩展中的硬件功能,该功能支持硬件更新页面表项中的访问(Access)和脏(Dirty)标志位。同样,如果向设置了 DBM 位的只读页面写入,将清除只读位(AP[2]),而不是触发权限故障。当在 TCR_EL1 寄存器(HA 和 HD 位)上启用此功能时,如果访问了清除了 PTE_AF 位的页面,则会设置该位,而不是触发访问标志故障。第2行到第6行为注释,含义为使能“硬件访问标记位”。原创 2024-09-25 09:06:37 · 663 阅读 · 0 评论 -
慢慢欣赏arm64内核启动22 primary_entry之__cpu_setup代码第四部分
在该宏定义里面,ID_AA64MMFR0_EL1, AArch64 Memory Model Feature Register 0。第4行涉及到宏定义 tcr_compute_pa_size 和 TCR_IPS_SHIFT。提供 EL1 异常模式下 内存模型和内存管理的信息,涉及到的宏定义如下。第1到第3行是注释,含义是设置 TCR_EL1 的 IPS 域。其中,tcr_compute_pa_size 的定义如下。我们可以看到 bit[3] 始终为0, 所以可以忽略掉。原创 2024-09-23 09:19:07 · 763 阅读 · 0 评论 -
慢慢欣赏arm64内核启动21 primary_entry之__cpu_setup代码第三部分
展示代码 /* * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for * both user and kernel. */ mov_q x10, TCR_TxSZ(VA_BITS) | TCR_CACHE_FLAGS | TCR_SMP_FLAGS | \ TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \ TCR_TBI0 | TCR_A1 | TC原创 2024-09-13 09:13:13 · 1054 阅读 · 0 评论 -
慢慢欣赏arm64内核启动20 primary_entry之__cpu_setup代码第二部分
【代码】慢慢欣赏arm64内核启动20 primary_entry之__cpu_setup代码第二部分。原创 2024-09-04 08:51:05 · 782 阅读 · 0 评论 -
慢慢欣赏arm64内核启动19 primary_entry之__cpu_setup代码第一部分
也就是说,位域bit12设置为1时,在EL0异常等级下,访问 MDCCSR_EL0, DBGDTR_EL0, DBGDTRTX_EL0, and DBGDTRRX_EL0 将会切换到 EL1 异常等级。第14, 15行涉及的寄存器 CPACR_EL1, Architectural Feature Access Control Register 的位域 bits[21:20]daifclr 涉及到 pstate 寄存器的 bits[9:6],分别是 DAIF,8对应 bit[9],表示清除调试掩码。原创 2024-09-02 09:41:38 · 837 阅读 · 0 评论 -
慢慢欣赏arm64内核启动18 primary_entry之__create_page_tables代码第五部分
【代码】慢慢欣赏arm64内核启动18 primary_entry之__create_page_tables代码第五部分。原创 2024-08-24 15:43:32 · 954 阅读 · 0 评论 -
慢慢欣赏arm64内核启动17 primary_entry之__create_page_tables代码第四部分map_memory剩下的流程
其中,表项的属性由 PMD_TYPE_TABLE 定义,rtbl 只定义了下一级页表的第一个页表起始地址,那么下一级页表的后续页表的起始地址需要根据 rtbl + n * PAGE_SIZE 而定。接着第7行,根据第6行,将 对应的下一级页表的物理地址 rtbl 填写到 本级页表也就是全局页表的表项,区间为 [start, iend],count 为0,表示全局页表的表项只在一个页表里面,不可能跨页表,当然 count 也当出参,统计全局页表的表项数目。n 代表第n个页表,n的范围为 [0, count)原创 2024-08-20 08:44:34 · 644 阅读 · 0 评论 -
慢慢欣赏arm64内核启动16 primary_entry之__create_page_tables代码第四部分populate_entries
我们没有使能 CONFIG_ARM64_PA_BITS_52,而是使能了 CONFIG_ARM64_PA_BITS_48,所以该宏就是把 rtbl,也就把是下一级的页表物理地址存放在 tmp1 里面。第19行将 tmp1 与 flags 进行或操作,也就是说,将页表基地址与页表属性组合在一起,由于页表基地值的有效位和页表属性的有效位在不同的位域里面,所以可以认为是缝合在一起。第1行到第16行时注释,大概意思是填充页表项,当前页表的每个页表项的内容是下一级页表的物理地址,所以牵扯到本级页表和下级页表。原创 2024-08-19 07:57:04 · 529 阅读 · 0 评论 -
慢慢欣赏arm64内核启动15 primary_entry之__create_page_tables代码第四部分compute_indices
第三个参数 shift 入参, 将虚拟地址转换为索引需要偏移的位数,调用者传过来的参数是 PGDIR_SHIFT,该参数我们在以前的章节中分析过,为39。第二个参数 vend 入参,虚拟地址的结束地址,在上一章节中我们是将 vend 自减1的,恰好符合注释描述的区间概念,否则就多分配了一个页表项。对于全局页表来说,最多就一个页,不会超过512,但是后面级别的页表就不好说了,只要全局页表的有效索引超过1,下一级的页表肯定是跨多个页表。根据注释,出参统计有效页表项的数目,包括了跨多个页表的场景。原创 2024-08-18 08:50:40 · 403 阅读 · 0 评论 -
慢慢欣赏arm64内核启动14 primary_entry之__create_page_tables代码第四部分map_memory
第二个参数 rtbl 是下一级页表的起始地址,根据刚才的描述,下一级页表的起始地址其实是不用传达的,注释也做了说明,由于全局目录只占有1个页面,所以在函数的内部是通过 tbl + PAGE_SIZE 传递的。第九个参数 iend,注释里没有说明,根据意思以及上下文代码的实现,应该是 index of end 的缩写,就是下一级页表的终止地址在该级页表的索引值,由于可能存在多个页表的可能性,第十二个参数 sv,也是出参,对应 x14,也是 临时变量,用于存储计算出来的下一级页表的起始物理地址。原创 2024-08-17 16:42:31 · 950 阅读 · 0 评论 -
慢慢欣赏arm64内核启动13 primary_entry之__create_page_tables代码第三部分
所以最终 PGDIR_SHIFT 的值为 ((PAGE_SHIFT - 3) * 4 + 3) == 39这就是 L0 索引的偏移PTRS_PER_PGD 的值为 1原创 2024-08-17 15:18:41 · 708 阅读 · 0 评论 -
慢慢欣赏arm64内核启动12 primary_entry之__create_page_tables代码第二部分
【代码】慢慢欣赏arm64内核启动12 primary_entry之__create_page_tables代码第二部分。原创 2024-08-11 15:35:36 · 328 阅读 · 0 评论 -
慢慢欣赏arm64内核启动11 primary_entry之__create_page_tables代码第一部分
【代码】慢慢欣赏arm64内核启动11 primary_entry之__create_page_tables代码第一部分.txt。原创 2024-08-10 10:14:28 · 361 阅读 · 0 评论 -
慢慢欣赏arm64内核启动10 primary_entry之set_cpu_boot_mode_flag
上面的文章我们分析完毕el2_setup函数,该函数虽长但不啰嗦。主要作用就是如果bootloader把控制权交给内核时,如果内核是EL1异常模式,则按照EL1模式初始化一些系统寄存器,然后返回w0为EL1;如果内核当前为EL2模式,则判断硬件是否支VHE,如果不支持,则切换到EL1;如果支持,则继续以EL2模式启动,这两种情况返回w0均为EL2。原创 2024-08-10 08:49:34 · 404 阅读 · 0 评论 -
慢慢欣赏arm64内核启动9 primary_entry之el2_setup代码第七部分
【代码】慢慢欣赏arm64内核启动9 primary_entry之el2_setup代码第七部分。原创 2024-08-07 13:53:50 · 134 阅读 · 0 评论 -
慢慢欣赏arm64内核启动8 primary_entry之el2_setup代码第六部分
【代码】慢慢欣赏arm64内核启动8 primary_entry之el2_setup代码第六部分。原创 2024-08-06 13:43:59 · 746 阅读 · 0 评论 -
慢慢欣赏arm64内核启动7 primary_entry之el2_setup代码第五部分
【代码】慢慢欣赏arm64内核启动7 primary_entry之el2_setup代码第五部分。原创 2024-08-06 08:51:25 · 656 阅读 · 0 评论 -
慢慢欣赏arm64内核启动6 primary_entry之el2_setup代码第四部分
【代码】慢慢欣赏arm64内核启动6 primary_entry之el2_setup代码第四部分。原创 2024-08-02 18:48:19 · 248 阅读 · 0 评论 -
慢慢欣赏arm64内核启动5 primary_entry之el2_setup代码第三部分
解析完虚拟化部分,我们继续分析启动过程中,对中断控制器的处理。原创 2024-08-02 05:15:52 · 551 阅读 · 0 评论 -
慢慢欣赏arm64内核启动4 primary_entry之el2_setup代码第二部分
el2_setup继续执行就到了EL2异常等级的虚拟化部分的解析和处理部分。原创 2024-07-30 13:46:43 · 525 阅读 · 0 评论 -
慢慢欣赏arm64内核启动3 primary_entry之el2_setup代码第一部分
分析完el2_setup的注释和代码段的位置之后,我们正式开始学习el2_setup的实现。原创 2024-07-30 08:39:44 · 238 阅读 · 0 评论 -
慢慢欣赏arm64内核启动2 primary_entry之el2_setup注释部分
primary_entry执行完保存参数的函数后,进入el2_setup函数查看调用函数的注释,含义是切换到EL1模式,出参为w0,保存进入内核时的异常等级。看到这个注释,我联想起异常返回章节的通过sppr_elX和elr_elX切换异常等级的方法,我们分析代码看看是否这样实现的。该函数较长,我们分段进行欣赏。原创 2024-07-29 07:47:56 · 231 阅读 · 0 评论 -
慢慢欣赏arm64内核启动1 primary_entry之保存启动参数
根据上一章节,bootloader将控制权交给内核,内核从__HEAD段的开头执行。该段的起始位置是_head。原创 2024-07-28 17:46:09 · 342 阅读 · 0 评论 -
慢慢欣赏arm64内核启动0 链接脚本.head.text部分的解析
HEAD_TEXT是指什么呢?我们搜索一下内核源码。原创 2024-07-24 08:41:46 · 250 阅读 · 0 评论 -
慢慢欣赏 ftrace (二)进程和中断状态填充方法
【代码】慢慢欣赏 ftrace (二)进程和中断状态填充方法。原创 2024-01-09 18:57:54 · 448 阅读 · 0 评论 -
慢慢欣赏 ftrace (一)找到解析function对应字段的函数
对于5.10内核,我们找到其对应函数 trace_print_context,该函数可以仔细研读。分析ftrace的时候,有时会对其字段部分不了解,有些字段解析的不清晰,例如D和~原创 2024-01-03 10:22:42 · 465 阅读 · 0 评论 -
慢慢欣赏linux 内核启动时将core0设置为自适应滴答模式失效
linux 4.19内核使能CONFIG_NO_HZ_FULL编译选项,生成内核之后,在bootloader启动参数指定core 0,4,5,6,7为自适应滴答模式,内核启动之后,发现core0并没有生效。查看内核日志,确认内核将core设置为自适应滴答模式之前,会将启动核core0剔除掉。有利于提高xenomai/PREEMPT-RT 实时性的一些配置建议。NO_HZ: 减少调度时钟的滴答。原创 2023-10-31 17:09:54 · 302 阅读 · 0 评论 -
慢慢欣赏linux 内核安装ko到指定的目录
linux内核安装ko到指定的目录原创 2022-10-08 17:31:10 · 1532 阅读 · 0 评论 -
查看软中断变化情况 linux性能优化学习之二
watch -d "/bin/cat /proc/softirqs | /usr/bin/awk 'NR == 1{printf \"%-15s %-15s %-15s %-15s %-15s\n\",\" \",\$1,\$2,\$3,\$4}; NR > 1{printf \"%-15s %-15s %-15s %-15s %-15s\n\",\$1,\$2,\$3,\$4,\$5}'"结果Every 2.0s: /bin/cat /proc/softirqs | /usr/bin/a.原创 2022-05-29 06:54:25 · 456 阅读 · 0 评论 -
慢慢欣赏linux 查看系统时钟信息
rlk@rlk:~$ sudo cat /proc/timer_list [sudo] password for rlk: Timer List Version: v0.8HRTIMER_MAX_CLOCK_BASES: 8now at 53391840158 nsecscpu: 0 clock 0: .base: ffff8a4639c1dfc0 .index: 0 .resolution: 1 nsecs .get_time: ktime_get.原创 2022-05-22 12:03:33 · 580 阅读 · 0 评论 -
慢慢欣赏linux pud_index和pud_page解析
#define pud_index(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1)) =>#define PUD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(1) =>#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n) ((PAGE_SHIFT - 3) * (4 - (n)) + 3) => 29 =>#define PTRS_PER_P.原创 2022-04-15 08:05:14 · 443 阅读 · 0 评论 -
慢慢欣赏linux pud_offset解析
typedef struct { pudval_t pud; } pud_t; =>typedef u64 pudval_t;#define pud_offset(dir, addr) ((pud_t *)__va(pud_offset_phys((dir), (addr)))) { =>#define pud_offset_phys(dir, addr) (pgd_page_paddr(READ_ONCE(*(dir))) + pud_index(addr) * sizeof(pu.原创 2022-04-13 06:48:06 · 747 阅读 · 0 评论 -
慢慢欣赏linux pgd_page解析
typedef struct { pgdval_t pgd; } pgd_t;#define pgd_page(pgd) pfn_to_page(__phys_to_pfn(__pgd_to_phys(pgd))){ =>#define __pgd_to_phys(pgd) __pte_to_phys(pgd_pte(pgd)) { =>static inline pte_t pgd_pte(pgd_t pgd) { return __pte(pgd_val.原创 2022-04-12 08:03:47 · 463 阅读 · 0 评论 -
慢慢欣赏linux 内核镜像剖析
linux kernel 5.0内核elf信息rlk@rlk:runninglinuxkernel_5.0$ readelf -h vmlinuxELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endi原创 2022-02-19 07:16:32 · 428 阅读 · 0 评论