当前位置: 首页 > news >正文

arm64异常向量表

arm64异常向量表

  • 1 arm64异常向量表
  • 2 linux arm64异常向量表
  • 3 kernel_ventry宏
  • 4 异常向量表的保存
    • 4. VBAR_ELx寄存器
    • 4.2 __primary_switched
    • 4.3 __primary_switched

1 arm64异常向量表

在这里插入图片描述
When an exception occurs, the processor must execute handler code which corresponds to the exception. The location in memory where the handler is stored is called the exception vector. In the ARM architecture, exception vectors are stored in a table, called the exception vector table. Each Exception level has its own vector table, that is, there is one for each of EL3, EL2 and EL1. The table contains instructions to be executed, rather than a set of addresses. Vectors for individual exceptions are located at fixed offsets from the beginning of the table. The virtual address of each table base is set by the Vector Based Address Registers VBAR_EL3, VBAR_EL2 and VBAR_EL1.
Each entry in the vector table is 16 instructions long. This in itself represents a significant change compared to ARMv7, where each entry was 4 bytes. This spacing of the ARMv7 vector table meant that each entry would almost always be some form of branch to the actual exception handler elsewhere in memory. In AArch64, the vectors are spaced more widely, so that the
top-level handler can be written directly in the vector table.
The base address is given by VBAR_ELn and then each entry has a defined offset from this base address. Each table has 16 entries, with each entry being 128 bytes (32 instructions) in size. The table effectively consists of 4 sets of 4 entries.
Which entry is used depends upon a number of factors:

  • The type of exception (SError, FIQ, IRQ or Synchronous)
  • If the exception is being taken at the same Exception level, the Stack Pointer to be used (SP0 or SPx)
  • If the exception is being taken at a lower Exception level, the execution state of the next lower level (AArch64 or AArch32)
    Considering an example might make this easier to understand.
    If kernel code is executing at EL1 and an IRQ interrupt is signaled, an IRQ exception occurs. This particular interrupt is not associated with the hypervisor or secure environment and is also handled within the kernel, also at SP_EL1, and the SPSel bit is set, so you are using SP_EL1. Execution is therefore from address VBAR_EL1 + 0x280.
    In the absence of LDR PC, [PC, #offset] in the ARMv8-A architecture, you must use more instructions to enable the destination to be read from a table of registers. The choice of spacing of the vectors is designed to avoid cache pollution for typical sized instruction cache lines from vectors that are not being used. The Reset Address is a completely separate address, which is
    IMPLEMENTATION DEFINED, and is typically set by hardwired configuration within the core. This address is visible in the RVBAR_EL1/2/3 register.
    Having a separate exception vector for each exception, either from the current Exception level or from the lower Exception level, gives the flexibility for the OS or hypervisor to determine the AArch64 and AArch32 state of the lower Exception levels. The SP_ELn is used for exceptions generated from lower levels. However, the software can switch to use SP_EL0 inside the
    handler. When you use this mechanism, it facilitates access to the values from the thread in the handler.

2 linux arm64异常向量表

/*                          * Exception vectors.       */                         .pushsection ".entry.text", "ax" .align  11          
SYM_CODE_START(vectors)    kernel_ventry   1, t, 64, sync          // Synchronous EL1t kernel_ventry   1, t, 64, irq           // IRQ EL1t kernel_ventry   1, t, 64, fiq           // FIQ EL1t kernel_ventry   1, t, 64, error         // Error EL1t kernel_ventry   1, h, 64, sync          // Synchronous EL1h kernel_ventry   1, h, 64, irq           // IRQ EL1h kernel_ventry   1, h, 64, fiq           // FIQ EL1h kernel_ventry   1, h, 64, error         // Error EL1h kernel_ventry   0, t, 64, sync          // Synchronous 64-bit EL0kernel_ventry   0, t, 64, irq           // IRQ 64-bit EL0kernel_ventry   0, t, 64, fiq           // FIQ 64-bit EL0kernel_ventry   0, t, 64, error         // Error 64-bit EL0                                                                                                                                        kernel_ventry   0, t, 32, sync          // Synchronous 32-bit EL0kernel_ventry   0, t, 32, irq           // IRQ 32-bit EL0kernel_ventry   0, t, 32, fiq           // FIQ 32-bit EL0kernel_ventry   0, t, 32, error         // Error 32-bit EL0
SYM_CODE_END(vectors)
  • .pushsection “.entry.text”, “ax” 表示要将当前的异常向量表放到.entry.text段,属性为"ax"
  • .align 11表示异常向量表的起始地址要2K对齐(2^11 = 2048),这和VBAR_ELx的寄存器定义是一致的。
  • SYM_CODE_START(vectors) 声明异常向量表

3 kernel_ventry宏

  • kernel_ventry是异常向量表的一部分通用处理宏,会依据参数跳转到不同的异常处理函数,对于kernel_ventry 1, h, 64, irq,则会跳转到el1h_64_irq处理函数流程中。
  • .align 7 表示当前的入口要按照128B对齐的方式去存放,这和异常向量表每个entry的大小为128B是匹配的
	.macro kernel_ventry, el:req, ht:req, regsize:req, label:req.align 7
.Lventry_start\@:.if	\el == 0/** This must be the first instruction of the EL0 vector entries. It is* skipped by the trampoline vectors, to trigger the cleanup.*/b	.Lskip_tramp_vectors_cleanup\@.if	\regsize == 64mrs	x30, tpidrro_el0msr	tpidrro_el0, xzr.elsemov	x30, xzr.endif
.Lskip_tramp_vectors_cleanup\@:.endifsub	sp, sp, #PT_REGS_SIZE
#ifdef CONFIG_VMAP_STACK/** Test whether the SP has overflowed, without corrupting a GPR.* Task and IRQ stacks are aligned so that SP & (1 << THREAD_SHIFT)* should always be zero.*/add	sp, sp, x0			// sp' = sp + x0sub	x0, sp, x0			// x0' = sp' - x0 = (sp + x0) - x0 = sptbnz	x0, #THREAD_SHIFT, 0fsub	x0, sp, x0			// x0'' = sp' - x0' = (sp + x0) - sp = x0sub	sp, sp, x0			// sp'' = sp' - x0 = (sp + x0) - x0 = spb	el\el\ht\()_\regsize\()_\label0:/** Either we've just detected an overflow, or we've taken an exception* while on the overflow stack. Either way, we won't return to* userspace, and can clobber EL0 registers to free up GPRs.*//* Stash the original SP (minus PT_REGS_SIZE) in tpidr_el0. */msr	tpidr_el0, x0/* Recover the original x0 value and stash it in tpidrro_el0 */sub	x0, sp, x0msr	tpidrro_el0, x0/* Switch to the overflow stack */adr_this_cpu sp, overflow_stack + OVERFLOW_STACK_SIZE, x0/** Check whether we were already on the overflow stack. This may happen* after panic() re-enables interrupts.*/mrs	x0, tpidr_el0			// sp of interrupted contextsub	x0, sp, x0			// delta with top of overflow stacktst	x0, #~(OVERFLOW_STACK_SIZE - 1)	// within range?b.ne	__bad_stack			// no? -> bad stack pointer/* We were already on the overflow stack. Restore sp/x0 and carry on. */sub	sp, sp, x0mrs	x0, tpidrro_el0
#endifb	el\el\ht\()_\regsize\()_\label
.org .Lventry_start\@ + 128	// Did we overflow the ventry slot?.endm

4 异常向量表的保存

异常向量表的保存分为两个部分,一个是主核的启动流程,另一个是副核的启动流程处理的。其处理函数分别为__primary_switched和__primary_switched

4. VBAR_ELx寄存器

VBAR_EL1, Vector Base Address Register (EL1),Holds the vector base address for any exception that is taken to EL1.
在这里插入图片描述

  • Bits [63:11]
    • Vector Base Address. Base address of the exception vectors for exceptions taken to EL1.
    • If the implementation does not support ARMv8.2-LVA, then:
      • If tagged addresses are being used, bits [55:48] of VBAR_EL1 must be the same or else the use of the vector address will result in a recursive exception.
      • If tagged addresses are not being used, bits [63:48] of VBAR_EL1 must be the same or else the use of the vector address will result in a recursive exception.
    • If the implementation supports ARMv8.2-LVA, then:
      • If tagged addresses are being used, bits [55:52] of VBAR_EL1 must be the same or else the use of the vector address will result in a recursive exception.
      • If tagged addresses are not being used, bits [63:52] of VBAR_EL1 must be the same or else the use of the vector address will result in a recursive exception.
        其访问方式如下所示:
  • MRS , VBAR_EL1 读取VBAR_EL1寄存器中保存的异常向量表地址到xt寄存器中
  • MSR VBAR_EL1, 将xt寄存器中保存的异常向量表地址写入VBAR_EL1寄存器中。

4.2 __primary_switched

对于主核的启动流程来说,其处理是如下两步,首先将vectors地址加载到x8寄存器中,随后通过msr指令,将其值写入vbar_el1寄存器中。

  • adr_l x8, vectors // load VBAR_EL1 with virtual
  • msr vbar_el1, x8 // vector table address
/** The following fragment of code is executed with the MMU enabled.**   x0 = __pa(KERNEL_START)*/
SYM_FUNC_START_LOCAL(__primary_switched)adr_l	x4, init_taskinit_cpu_task x4, x5, x6adr_l	x8, vectors			// load VBAR_EL1 with virtualmsr	vbar_el1, x8			// vector table addressisbstp	x29, x30, [sp, #-16]!mov	x29, spstr_l	x21, __fdt_pointer, x5		// Save FDT pointerldr_l	x4, kimage_vaddr		// Save the offset betweensub	x4, x4, x0			// the kernel virtual andstr_l	x4, kimage_voffset, x5		// physical mappingsmov	x0, x20bl	set_cpu_boot_mode_flag// Clear BSSadr_l	x0, __bss_startmov	x1, xzradr_l	x2, __bss_stopsub	x2, x2, x0bl	__pi_memsetdsb	ishst				// Make zero page visible to PTW#if VA_BITS > 48adr_l	x8, vabits_actual		// Set this early so KASAN early initstr	x25, [x8]			// ... observes the correct valuedc	civac, x8			// Make visible to booting secondaries
#endif#ifdef CONFIG_RANDOMIZE_BASEadrp	x5, memstart_offset_seed	// Save KASLR linear map seedstrh	w24, [x5, :lo12:memstart_offset_seed]
#endif
#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)bl	kasan_early_init
#endifmov	x0, x21				// pass FDT address in x0bl	early_fdt_map			// Try mapping the FDT earlymov	x0, x20				// pass the full boot statusbl	init_feature_override		// Parse cpu feature overridesmov	x0, x20bl	finalise_el2			// Prefer VHE if possibleldp	x29, x30, [sp], #16bl	start_kernelASM_BUG()
SYM_FUNC_END(__primary_switched)

4.3 __primary_switched

对于副核的启动流程来说,其处理是如下两步,首先将vectors地址加载到x5寄存器中,随后通过msr指令,将其值写入vbar_el1寄存器中。

  • adr_l x5, vectors
  • msr vbar_el1, x5
SYM_FUNC_START_LOCAL(__secondary_switched)mov	x0, x20bl	set_cpu_boot_mode_flagstr_l	xzr, __early_cpu_boot_status, x3adr_l	x5, vectorsmsr	vbar_el1, x5isbadr_l	x0, secondary_dataldr	x2, [x0, #CPU_BOOT_TASK]cbz	x2, __secondary_too_slowinit_cpu_task x2, x1, x3#ifdef CONFIG_ARM64_PTR_AUTHptrauth_keys_init_cpu x2, x3, x4, x5
#endifbl	secondary_start_kernelASM_BUG()
SYM_FUNC_END(__secondary_switched)

相关文章:

arm64异常向量表

arm64异常向量表1 arm64异常向量表2 linux arm64异常向量表3 kernel_ventry宏4 异常向量表的保存4. VBAR_ELx寄存器4.2 __primary_switched4.3 __primary_switched1 arm64异常向量表 When an exception occurs, the processor must execute handler code which corresponds to …...

【测试面试】吐血整理,大厂测试开发岗面试题(1~4面),拿下年40w...

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 自动化测试面试题&am…...

SpringSecurity之权限模块设计

目录 前言 实现思路 代码结构 使用说明 前言 前面我们了解了关于微服务权限设计方案以及J W T的相关介绍&#xff0c;今天我们来聊一下&#xff0c;如何避免自己重复的写相同的代码&#xff0c;一次代码实现&#xff0c;即可完美复制到任何项目中实现权限相关的功能。 实现…...

002_双指针法

1.移除元素 目标&#xff1a;移除数组中的某一个元素 数组的元素在内存地址中是连续的&#xff0c;不能单独删除数组中的某个元素&#xff0c;只能覆盖。 1.1暴力解法 建立两个for循环&#xff0c;当查找到某个元素以后&#xff0c;将此元素后面的元素全部往前移动 时间复…...

超实用的 Linux 高级命令,程序员一定要懂

前言 在运维的坑里摸爬滚打好几年了&#xff0c;我还记得我刚开始的时候&#xff0c;我只会使用一些简单的命令&#xff0c;写脚本的时候&#xff0c;也是要多简单有多简单&#xff0c;所以有时候写出来的脚本又长又臭。 像一些高级点的命令&#xff0c;比如说 Xargs 命令、管…...

AI+明厨亮灶智能算法 yolo

AI明厨亮灶智能算法通过pythonyolo网络模型分析算法&#xff0c;AI明厨亮灶模型算法可接对后厨实现如口罩识别、厨师服穿戴、夜间老鼠监测、厨师帽识别、厨师玩手机打电话识别、抽烟识别等实时分析监测。Python是一种由Guido van Rossum开发的通用编程语言&#xff0c;它很快就…...

gRPC-Go源码解读一 客户端请求链路分析

最近在学习gRPC相关的知识&#xff0c;为啥要学呢&#xff1f;因为一直在用&#xff0c;古人云&#xff0c;“工欲善其事&#xff0c;必先利其器”。为此&#xff0c;花了不少时间阅读gRPC-Go的源码&#xff0c;收货甚多&#xff0c;比如透过服务发现和负载均衡这俩组件来学习复…...

Word控件Spire.Doc for .net 功能详解

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…...

联想服务器配置RAID

一、背景描述 目前有台联想服务器&#xff0c;配置如下&#xff1a; CPU&#xff1a;2颗处理器&#xff0c;40核 内存&#xff1a;512GB 磁盘&#xff1a;2*960GB SATA 4*2.4TB SAS 计划在联想物理机上安装 Vmware 的 ESXi 6.7 虚拟化管理软件&#xff0c;作为虚拟化服务器。…...

C++ 虚函数表

在 C 中&#xff0c;虚函数表&#xff08;Virtual Function Table&#xff0c;简称 vtable&#xff09;是一种用于实现多态性&#xff08;Polymorphism&#xff09;的机制。它是一种编译器和链接器生成的数据结构&#xff0c;用于处理虚函数调用。 虚函数是在基类中声明的&…...

rancher2.7丢失集群信息

使用Docker 单节点安装rancher&#xff0c;然后在rancher中创建了一个k8s的集群。重启rancher所在的虚拟机后&#xff0c;登录rancher发现这是新的实例&#xff0c;集群信息丢失了。但是k8s集群还是好好的。 检查k8s的日志&#xff0c;api server日志会报错 time"2023-0…...

数据库管理-第六十八期 Oracle 23c的其他(20230417)

数据库管理 2023-04-17第六十八期 Oracle 23c的其他1 DGPDB2 无锁并发总结第六十八期 Oracle 23c的其他 由于Oracle 23c的文档相对较少&#xff0c;一是当前文档主要面向开发人员&#xff0c;二是感觉实际内容还在不断增加&#xff0c;主要还有一点就是各种新特性的在官方文档…...

精准关键词获取-行业搜索词分析

SEO关键词的收集通常可以通过以下几种方法&#xff1a; 根据市场价值、搜索词竞争性和企业实际产品特征进行筛选&#xff1a;确定您的关键词列表之前&#xff0c;建议先进行市场分析&#xff0c;了解您的竞争对手、行业状况和目标受众等信息&#xff0c;以更好的了解所需的特定…...

c++学习之c++对c的扩展1

目录 1.面向过程与面向对象的编程 2.面向对象编程的三大特点 3.c对c的扩展&#xff1a; 1.作用域运算符&#xff1a;&#xff1a; 2.命名空间 1.c命名空间&#xff08;namespace&#xff09; 2.命名空间的使用 1.在不同命名空间内可以创建相同的名称 2.命名空间只能在全…...

Redis锁的租约问题

目录Redis的租约问题Redis租约问题的想法Redis租约问题的解决方案Redis的租约问题 首先我们先来说一说什么是Redis的租约问题。   在我们实现Redis分布式锁的时候&#xff0c;我们会出现Redis锁的时间<业务执行执行时间&#xff0c;这其实就是一个典型的租约问题&#xf…...

2023年全国最新高校辅导员精选真题及答案50

百分百题库提供高校辅导员考试试题、辅导员考试预测题、高校辅导员考试真题、辅导员证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 94.一般认为&#xff0c;在具有了道德认知和道德情感的情况下&#xff0c;道德行为的产生…...

mall商城之k8s部署-4

文章目录 一、k8s部署应用服务1)master拷贝yaml2)批量修改镜像地址3)批量修改nacos地址3)创建命名空间4)创建取sercet5)配置yaml6)对象存储oss7)查看nacos1、导入配置文件2、修改配置文件8)部署到ms命名空间一、k8s部署应用服务 1)master拷贝yaml #将源码文件 mkdi…...

使用Go语言打造轻量级Web框架

前言 Web框架是Web开发中不可或缺的组件。它们的主要目标是抽象出HTTP请求和响应的细节&#xff0c;使开发人员可以更专注于业务逻辑的实现。在本篇文章中&#xff0c;我们将使用Go语言实现一个简单的Web框架&#xff0c;类似于Gin框架。 功能 我们的Web框架需要实现以下功能…...

【开源项目】BallCat 项目脚手架

简介 &#x1f389;&#x1f389;&#x1f389; 基于 React 和 Ant Design 版本的前端 ballcat-ui-react 已发布&#xff0c;欢迎大家尝鲜使用 BallCat 组织旨在为项目快速开发提供一系列的基础能力&#xff0c;方便使用者根据项目需求快速进行功能拓展。 在以前使用其他后台管…...

KlayGE-004-InputCaps 例子分析

InputCaps处理外部输入的事件 该例子主要由两部分内容&#xff1a; 外部输入事件获取 ​ 可以处理keyboard、mouse、joystick、touch、sensor的输入事件 显示一个ui图标按钮 Input 定义监听事件类型&#xff1a; KlayGE::InputActionDefine actions[] {InputActionDefin…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...