内核启动过程中对CPU型号的确认

2023-11-18

1、内核为什么要确认CPU型号

内核和CPU都是不断发展的,内核会不断的更新版本,CPU会不断的出新型号。每当厂商推出一款新的CPU都需要移植内核,使内核能在新款CPU上运行。如果我们将没有针对该款CPU移植过的内核放到该款CPU上运行,结果就是运行不起来。所以内核在内部维护了一张支持CPU型号的表,在启动时内核会确认当前CPU型号是否在表中,如果不在,说明内核不支持该款CPU,终止启动。

2、内核维护支持的CPU型号表

2.1、 * (.proc.info.init)段

/*摘抄自内核的链接文件*/
 __proc_info_begin = .;
   *(.proc.info.init)
  __proc_info_end = .;

内核在链接时会将proc.info.init段属性的代码链接在一起,标号__proc_info_begin代表段的起始地址,标号__proc_info_end代表段的结束地址。proc.info.init段都是支持的CPU型号的信息,在启动时就根据段的起始地址和结束地址,在表格中遍历看是否能找到当前的CPU型号。

2.2、描述CPU信息的"proc_info_list"结构体

struct proc_info_list {
	unsigned int		cpu_val;
	unsigned int		cpu_mask;
	unsigned long		__cpu_mm_mmu_flags;	/* used by head.S */
	unsigned long		__cpu_io_mmu_flags;	/* used by head.S */
	unsigned long		__cpu_flush;		/* used by head.S */
	const char		*arch_name;
	const char		*elf_name;
	unsigned int		elf_hwcap;
	const char		*cpu_name;
	struct processor	*proc;
	struct cpu_tlb_fns	*tlb;
	struct cpu_user_fns	*user;
	struct cpu_cache_fns	*cache;
};

proc_info_list结构体就是用来描述CPU信息的,

2.3、把CPU对应的proc_info_list结构体放入 * (.proc.info.init)段

	.section ".proc.info.init", #alloc, #execinstr

	/*
	 * Match any ARMv7 processor core.
	 */
	.type	__v7_proc_info, #object
__v7_proc_info:
	.long	0x000f0000		@ Required ID value
	.long	0x000f0000		@ Mask for ID
	.long   PMD_TYPE_SECT | \
		PMD_SECT_AP_WRITE | \
		PMD_SECT_AP_READ | \
		PMD_FLAGS
	.long   PMD_TYPE_SECT | \
		PMD_SECT_XN | \
		PMD_SECT_AP_WRITE | \
		PMD_SECT_AP_READ
	b	__v7_setup
	.long	cpu_arch_name
	.long	cpu_elf_name
	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
	.long	cpu_v7_name
	.long	v7_processor_functions
	.long	v7wbi_tlb_fns
	.long	v6_user_fns
	.long	v7_cache_fns
	.size	__v7_proc_info, . - __v7_proc_info

对于ARM架构的CPU,表示支持的CPU的源码定义在在arch/arm/mm/目录下。上面的proc_info_list结构体的信息摘抄自arch/arm/mm/proc-v7.S文件,任何ARMv7架构的CPU都是适用此结构体里的信息。
(1).section “.proc.info.init”:表示此处开始的内容属于".proc.info.init"段,也就是后面的proc_info_list结构体,在链接的程序的时候就会把proc_info_list结构体链接在一起,再根据标号的开始、结束地址去遍历proc_info_list结构体。

3.内核中启动时确认CPU型号

	@摘抄自内核启动的汇编代码
	mrc	p15, 0, r9, c0, c0		@ get processor id, CPU的ID号
	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
	movs	r10, r5				@ invalid processor (r5=0)?
	beq	__error_p			@ yes, error 'p'

(1)从CP15协处理器的c0寄存器读出CPU的ID号到r9寄存器;
(2)调用__lookup_processor_type函数查询内核支持的CPU型号中是否有当前CPU;
(3)如果没有匹配到CPU型号,则r5寄存器的值是0;如果查询到则r5寄存器的值是CPU对应proc_info_list结构体的地址;
(5)没有匹配到CPU型号则报错,终止启动;

3.1、__lookup_processor_type汇编函数

@此时r9保存的是从协处理器读取到的processor id
__lookup_processor_type:
	adr	r3, 3f	@将往后的标号3的地址加载到r3寄存器中,也就是__proc_info_begin
	ldmia	r3, {r5 - r7}  
	add	r3, r3, #8			@r3=r3+8,此时r3寄存器的值的等于标号4的地址
	sub	r3, r3, r7			@ 得到虚拟地址和物理地址的差值,r3=r3-r7
	add	r5, r5, r3			@ 将r5中保存的虚拟地址转换成物理地址
	add	r6, r6, r3			@ 将r6中保存的虚拟地址转换成物理地址
1:	ldmia	r5, {r3, r4}		@ r3存的cpu_val, r4存的cpu_mask
	and	r4, r4, r9			@ 将r9存的processor id 和cpu_mask相与:r4=r4 & r9
	teq	r3, r4				@判断r3和r4是否相等
	beq	2f						@如果r3=r4,则跳转到标号2处
	add	r5, r5, #PROC_INFO_SZ		@ sizeof(proc_info_list)	@r5=r5+ #PROC_INFO_SZ
	cmp	r5, r6				@判断r5是否等于r6,如果相等说明已经遍历完全部的proc_info_list结构体
	blo	1b					@r5!=r6则跳转到标号1处
	mov	r5, #0				@ r5=0,说明没有匹配到CPU型号
2:	mov	pc, lr					@函数返回
ENDPROC(__lookup_processor_type)

3:	.long	__proc_info_begin	@链接脚本里proc_info_list结构体的起始地址
	.long	__proc_info_end	@链接脚本里proc_info_list结构体的结束地址
4:	.long	.
	.long	__arch_info_begin
	.long	__arch_info_end

汇编语言解析:
(1)adr r3, 3f:将标号3的地址加载到r3中,adr是加载的是运行时地址,也就是物理地址;
(2)ldmia r3, {r5 - r7} :将r3寄存器的值已经往后的值一次存在r5 - r7寄存器中。该语句的作用就是把long __proc_info_begin存在r5,__proc_info_end存到r6,标号4的地址存到r7。
(3)sub r3, r3, r7:此时r3里是标号4的物理地址,r4存的是标号4的链接地址,也就是虚拟地址;
(4)ldmia r5, {r3, r4}:r5存的是proc_info_list结构体的地址,而结构体的前两个成员就是cpu_val和cpu_mask;
(5)add r5, r5, #PROC_INFO_SZ:指向下一个proc_info_list结构体,理解成C语言就是**(proc_info_list *)r5++**;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

内核启动过程中对CPU型号的确认 的相关文章

  • 抢占的中断处理程序会发生什么?

    即使在一些写得很好的内核书籍中 我也找不到以下问题的正确答案 他们说 ISR 无法休眠 因为它无法重新调度 ISR 因为它没有与任何进程连接 那么当更高优先级的中断抢占正在执行的中断时会发生什么 中断的 ISR 不会再次重新调度 执行 如果
  • “互斥锁”到底有什么作用?

    您可以在此链接中看到一个有趣的表格 http norvig com 21 days html answers http norvig com 21 days html answers 该表描述 互斥锁 解锁 25 nanosec 从主存中获
  • 在内核空间中存储结构体数组,Linux

    我相信我可能有点过度思考这个问题 我的文件系统上有一个文本文件 我在启动时解析该文件并将结果存储到结构数组中 我需要将此数组从用户空间复制到内核空间 copy from user 并且必须让内核随时可以访问此数据 内核空间中的数据需要通过
  • 内核:如何从进程的task_struct中找到所有线程?

    给定一个进程或线程的任务结构 迭代属于同一进程的所有其他线程的习惯用法是什么 Linux 不区分进程 任务 和线程 库调用 fork 和 pthread create 使用相同的系统调用 clone fork 和 pthread creat
  • Linux内核AIO,开放系统调用

    为什么 Linux 内核 AIO 不支持异步 开放 系统调用 因为 打开 可能会长时间阻塞文件系统 不是吗 首先 这是一个非常好的 合理的问题 不幸的是 它可能会赶走比我更有知识的人 AFAICT 没有good原因 您设法挖掘的讨论是相关的
  • 自制内核链接器全局变量和内联字符串无法访问

    我遵循了网上的一些教程并创建了自己的内核 它在带有 QEMU 的 GRUB 上成功启动 但我遇到了中描述的问题这个问题 https stackoverflow com questions 11305075 simple c kernel c
  • 如何在内核程序(内核上下文)中访问用户程序创建的bpf映射?

    假设有两个程序 用户程序和内核程序 用户程序通过api制作bpf图bpf create map name 返回 fd 有了这个 fd 我可以通过系统调用访问地图 例如 bpf map update FD 但我只能在用户空间程序中执行此操作
  • 内存映射 IO - 它是如何完成的?

    我已经了解了端口映射 IO 和内存映射 IO 之间的区别 但我无法弄清楚内存映射 Io 在现代操作系统 windows 或 linux 中是如何实现的 我所知道的是 物理内存的一部分被保留用于与硬件通信 并且有一个 MMIO 单元负责处理总
  • 如何安排Makefile来编译具有多个.c文件的内核模块?

    如何安排Makefile来编译具有多个 c文件的内核模块 这是我当前的 Makefile 它是由自动生成的KDevelop http www kdevelop org TARGET nlb driver OBJS nlb driver o
  • Linux调度程序需要上下文切换吗?

    我有一个关于 linux 调度程序和其他一些类似的内核系统调用的一般问题 Linux调度程序是否被视为一个 进程 并且对调度程序的每次调用都需要像另一个进程一样进行上下文切换 假设我们有一个时钟滴答声 它会中断当前正在运行的用户模式进程 现
  • Linux 中的内存区域标志:为什么需要 VM_WRITE 和 VM_MAYWRITE?

    Mel Gorman 的 Understanding the Linux Virtual Memory Manager 2007 年 这是本书章节链接 https www kernel org doc gorman html underst
  • /arm64/Image 到 zImage 或 boot.img

    大家好 我一直在试图弄清楚如何使我的 android 内核成为 zImage 或 boot img 我试图弄清楚但没有运气 有人告诉我 zImage 不适用于我的设备 因为它是 arm64 内核 但我想我会再问一次 如果是这种情况 我会尝试
  • unix/linux 套接字中的阻塞模式如何工作?

    阻塞模式是否将该特定任务置于 进程等待 状态 因为我认为非阻塞套接字需要用户明确的 忙等待 或 自旋锁 实现 或者阻塞模式套接字只不过是内核忙等待的隐式实现 在信号量 互斥体 监视器等锁定机制中 通常通过将任务推入阻塞状态来实现锁定 我认为
  • 破坏用户空间是什么意思? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 这可能是一个简单的问题 但是 我听说在内核上工作的唯一规则是不要破坏 用户空间 所以我想知道这意味着什么 打破用户空间这是怎么发生的 Ed
  • Linux内核中的模块间通信

    我有两个 Linux 内核模块 其中一个可以为另一个提供一些功能 但使用该功能并不是必需的 即使第一个模块不存在 第二个模块也可以 并且应该 工作 如果我只是从第一个模块导出函数并在第二个模块中使用它 则第二个模块依赖于该符号 并且在没有第
  • USBInterfaceOpen总是报kIOReturnExclusiveAccess错误

    最近我遇到了这个问题 很头疼 我已经在这个问题上花了一个星期了 但仍然失败 希望您能帮我把这块石头踢开 非常感谢 我的问题 我们公司为iPhone生产USB存储设备 实际上这个存储设备中有一个SDCard 现在 我们想要开发一个 Mac 应
  • 在执行期间访问.eh_frame数据

    我正在尝试访问以下内容 eh frame正在运行的程序的一部分 具体来说 该程序是 Linux 内核 2 6 34 8 这 eh frame包含用于异常处理的有用数据 我想在内核代码内部使用它 该部分已经由以下人员编写gcc readelf
  • Alsa 带有来自调制解调器的 PCM 接口

    我有一个基于 imx28 CPU 的定制板 CPU 的串行端口连接到调制解调器的 PCM 输出 我必须为调制解调器的 PCM 接口开发一个驱动程序 使其成为 ALSA SoC 的一部分 您能指出内核树 中与我的设置重新组合的一些驱动程序吗
  • 没有设备的设备驱动程序?

    我正在创建一个需要使用一些内核级模块的应用程序 为此我将应用程序分为 2 个 一个用户级程序和一个内核级程序 在阅读了有关设备驱动程序并浏览一些教程后 我有点困惑 是否可以存在没有任何特定设备与之关联的设备驱动程序 除了设备驱动程序 内核代
  • 在Linux中断上下文中运行用户线程

    我正在编写一些定制的应用程序 并允许更改 Linux 内核中的中断处理程序代码 我有一个用户线程正在等待中断发生 如果发生中断 那么我要做的第一件事就是执行该用户线程 有什么办法让它发挥作用吗 Thanks 创建一个字符设备 这就是内核所做

随机推荐

  • django解决跨域的方法,django如何解决跨域问题,django如何跨域

    django 使三方工具包解决跨域问题 1 安装 pip install django cors headers 2 到django的配置文件settings py中配置 1 注册到app中 INSTALLED APPS corsheade
  • Thread.UncaughtExceptionHandler

    1 自定义Application继承Application 在清单文件中将默认的Application的android name 替换成自定义的Application对象名称即可 在Oncreate中写入要实现的内容 2 在编写APK程序时
  • SpringBoot @EnableAutoConfiguration exclude属性失效

    在学习SpringBoot的时候 入了不少的坑 今天学习 SpringBootApplication里面的 EnableAutoConfiguration注解的exclude属性的 加载配置中 发现了属性失效的case 病状 exclude
  • NMEA协议解析

    文章目录 一 NMEA0183协议 1 NMEA基本框架 2 常用语句 1 GNGGA 2 GNGLL 3 GNGSA 4 GPGSV 5 GNRMC 6 GNVTG 7 GNZDA 8 PAIRCLK等 二 异或校验和代码 1 网址在线计
  • Pycharm启动失败的可能原因之一

    下载好Python后下载Pycharm应用 但是点击应用配置后有时启动失败 有时弹框提示错误 看进程均不占CPU 尝试网上各种解决方案 重新下载软件 重装系统都没能解决 最终发现是因为电脑上装的加密软件导致 卸载后重新安装即可 Pychar
  • 解决 java.lang.noclassdeffounderror: XXX 相关问题

    本文能临时解决所有与noclassdeffounderror相关的报错 首先说下这个错误 它表示你在运行的时候没有找到这个包 但是我们在编译的时候反而有这个包 这里需要理解下 我们java在编译和运行的时候都会编译jar包 但是你肯定是id
  • 记一次Spark打包错误:object java.lang.Object in compiler mirror

    使用maven compile和package 一直报错scala reflect internal MissingRequirementError object scala runtime in compiler mirror not f
  • 【Linux】实现简易的Shell命令行解释器

    大家好我是沐曦希 文章目录 一 前言 二 准备工作 1 输出提示符 2 输入和获取命令 3 shell运行原理 4 内建命令 5 替换 三 整体代码 一 前言 前面学到了进程创建 进程终止 进程等待 进程替换 那么通过这些来制作一个简易的S
  • 多任务:分层特征融合网络 NDDR-CNN

    论文链接 NDDR CNN 论文摘要 In this paper we propose a novel Convolutional Neural Network CNN structure for general purpose multi
  • sqli-labs/Less-34

    这一关虽然属于宽字节注入 但是回归了post请求了 而且欢迎界面还是存在转义之后的样子和十六进制的样子 首先我们试试在username处输入admin 转义之后变成了admin 所以我们进行宽字节注入将注入修改为admin c0 结果界面还
  • 微信小程序隐私保护指引设置

    今天修改了发布规则 发布前必须填写用户隐私保护指引设置 就是以下内容
  • 解决Unity导出的APK启动黑屏的问题

    今天准备把最近写的Unity游戏编一个版本 但是放真机上运行时 一启动就黑屏 网上各种查资料 折腾半天后 找到了解决方案 需要指定Graphics APIs 为OpenGLES3 在 Project Settings gt Player g
  • sort中用lambda函数(看完就会)

    介绍 sort函数是默认从小到大排列的 如果我们想要改变排序方式就要自己写个cmp函数 如果排列方式比较简单的话我们可以在sort函数中用一个简单的lambda函数 源码及讲解 对非结构体的数组 前面的 表示对数的操作方式 如果填个 说明是
  • shell指令,通过函数实现数组求和,通过函数获取用户uid和gid

    一 实现一个对数组求和的函数 数组通过实参传递给函数 num 0 read p 请输入一组数据 a arr function add for i 0 i lt arr i do num arr i done return num add a
  • CSS中如何实现文字描边效果(Text Stroke)?

    聚沙成塔 每天进步一点点 专栏简介 文字描边效果 Text Stroke 示例 写在最后 专栏简介 前端入门之旅 探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅 这个专栏是为那些对
  • 手把手接入【微信测试公众号】,不会还有人不会调试公众号吧?

    仅使用微信的测试公众号 Java开发内容 遇错与参考 Java接入测试微信公众号调试流程 前提 创建并配置测试号 登陆注册微信测试公众号 沙箱 微信验签 免登授权获取用户信息 微信接口调试工具的使用 创建服务号菜单 常见错误 invalid
  • 最高月薪15K! 这个30岁的奶茶店老板说:这次转行,转对了!

    人生没有一成不变的风景 这一路上 我们会走过晴天 也会踏过泥泞 会穿越风雨 也将沐浴暖阳 不同的年龄 有不同的风景 不同的阶段 有不同的境遇 也许每个人的经历不同 对人生的感受也各异 但只要内心强大 不断让自己淬炼成长 就能从容面对人生 行
  • Yii Framework 开发教程(47) 主题 Theme 示例

    Theming是一个在Web应用程序里定制网页外观的系统方式 通过采用一个新的主题 可以非常方便的改变应用的外观 在Yii 每个主题由一个目录代表 包含view文件 layout文件和相关的资源文件 如图片 CSS文件 JavaScript
  • 1、安装配置

    一 安装 这里以Redis 5 0 5版本为例 实际安装过程中 可以去官网下载最新的稳定版本 官网地址 http redis io download wget http download redis io releases redis 5
  • 内核启动过程中对CPU型号的确认

    1 内核为什么要确认CPU型号 内核和CPU都是不断发展的 内核会不断的更新版本 CPU会不断的出新型号 每当厂商推出一款新的CPU都需要移植内核 使内核能在新款CPU上运行 如果我们将没有针对该款CPU移植过的内核放到该款CPU上运行 结