ARM64学习笔记---建立异常向量表(二)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

源码:

#include "mm.h"
#include "sysregs.h".section  .rodata
.align 3
.globl el_string1
el_string1:.string "Booting at EL".section ".text.boot"
.globl _start
_start://读取mpidr_el1寄存器的值,该寄存器决定了代码运行在哪个核心上mrs	x0, mpidr_el1		 //提取mpidr_el1寄存器的低8位and	x0, x0,#0xFF		// Check processor id//如果全零,说明代码运行在CPU0上cbz	x0, master		// Hang for all non-primary CPU//如果代码不是运行在CPU0上则挂死b	proc_hangproc_hang: b 	proc_hangmaster:/* init uart and print the string*/bl __init_uart/* init uart and print the string*///初始化串口打印bl __init_uart//读取当前EL状态mrs x5, CurrentEL//如果是处于EL3说明异常了,调用异常返回cmp x5, #CurrentEL_EL3b.eq el3_entry//否则调用EL2的处理b el2_entryel3_entry:eretel2_entry:bl print_el/* The Execution state for EL1 is AArch64 HCR_EL2寄存器中有一个RW域(Bit[31]),它记录了异常发生后ELI要处在哪个执行 状态下。 □ 1表示在AArch64执行状态下。 □ 0表示在AArch32执行状态下。*/ldr x0, =HCR_HOST_NVHE_FLAGSmsr hcr_el2, x0//EL1页表还未建立,因此需要关闭MMUldr x0, =SCTLR_VALUE_MMU_DISABLEDmsr sctlr_el1, x0/*因为当前处于EL2,所以发生异常前(EL2切换到EL1本质上是一种异常发生),需要填充当前等级的SPSR,也就是SPSR_EL2,当异常返回的时候(eret)时,再从SPSR_EL2恢复到PSTATE*//*关闭D,A,I,F(关闭中断等),同时设置异常返回的等级,因为我们希望切换到EL1,因此这里设置EL2的异常返回等级为EL1h,这里的 h 代表使用的是SP_EL1作为栈指针*/ldr x0, =SPSR_EL1msr spsr_el2, x0/*PC相对地址加载指令,将el1的入口函数地址赋值给x0寄存器,这里注意和adrp的区别,adrp返回的地址是4K对齐,这样的话就不是函数的地址了*/adr x0, el1_entry/*将x0寄存器赋值给elr_el2,这里是设置el2的异常返回地址*/msr elr_el2, x0/*el2异常返回,程序流程会进入到el1*/eretel1_entry:bl print_el/* 设置异常向量表基地址到vbar寄存器 */ldr     x5, =vectorsmsr     vbar_el1, x5isb//bss段清零adr	x0, _bssadr	x1, _ebsssub	x1, x1, x0bl 	memzero/*预留栈空间*/mov	sp, #LOW_MEMORY /*跳转到C函数*/bl	kernel_mainb 	proc_hang		// should never come hereprint_el://先保存LR寄存器,保存子程序的返回地址,避免被破坏mov x10, x30/*print EL*/adrp x0, el_string1add x0, x0, :lo12:el_string1bl put_string_uartmrs x5, CurrentEL/* get the currentEL value *//*CurrentEL寄存器的 [2:3] 保存的是当前异常等级,因此这里右移2位后赋值给x2寄存器*/lsr x2, x5, #2//48指的是ASCII码为0mov x0, #48// ‘0’ + 具体的EL值,得到相应EL等级的ASCII码add x0, x0, x2// 将x0(EL具体值)作为入参传达给串口打印出来bl put_uart/* print the new line tab *///打印换行符mov x0, #10bl put_uart//恢复LR寄存器mov x30, x10ret

异常向量表的实现:

#define BAD_SYNC        0
#define BAD_IRQ         1
#define BAD_FIQ         2
#define BAD_ERROR       3/*处理无效的异常向量*/.macro inv_entry el, reason//kernel_entry el//第一个参数是pt_regs(寄存器框架大小),这个实验并没有用到mov x0, sp//"\reason" 汇编中表示引用入参mov x1, #\reason//根据寄存器esr_el1来解析同步异常mrs x2, esr_el1//跳转到C代码b bad_mode.endm/*vector table entry每个表项是128字节, align 7表示128字节对齐*/.macro vtentry label.align 7b \label.endm/** Vector Table** ARM64的异常向量表一共占用2048个字节* 分成4组,每组4个表项,每个表项占128字节* 参见ARMv8 spec v8.6第D1.10节* align 11表示2048字节对齐*/
.align 11
.global vectors
vectors:/* Current EL with SP0当前系统运行在EL1时使用EL0的栈指针SP这是一种异常错误的类型*/vtentry el1_sync_invalidvtentry el1_irq_invalidvtentry el1_fiq_invalidvtentry el1_error_invalid/* Current EL with SPx当前系统运行在EL1时使用EL1的栈指针SP这说明系统在内核态发生了异常Note: 我们暂时只实现IRQ中断*/vtentry el1_sync_invalidvtentry el1_irq_invalidvtentry el1_fiq_invalidvtentry el1_error_invalid/* Lower EL using AArch64在用户态的aarch64的程序发生了异常*/vtentry el0_sync_invalidvtentry el0_irq_invalidvtentry el0_fiq_invalidvtentry el0_error_invalid/* Lower EL using AArch32在用户态的aarch32的程序发生了异常*/vtentry el0_sync_invalidvtentry el0_irq_invalidvtentry el0_fiq_invalidvtentry el0_error_invalidel1_sync_invalid:inv_entry 1, BAD_SYNC
el1_irq_invalid:inv_entry 1, BAD_IRQ
el1_fiq_invalid:inv_entry 1, BAD_FIQ
el1_error_invalid:inv_entry 1, BAD_ERROR
el0_sync_invalid:inv_entry 0, BAD_SYNC
el0_irq_invalid:inv_entry 0, BAD_IRQ
el0_fiq_invalid:inv_entry 0, BAD_FIQ
el0_error_invalid:inv_entry 0, BAD_ERRORstring_test:.string "t".global trigger_alignment
trigger_alignment:ldr x0, =0x80002ldr x1, [x0]ret

不同异常问题构造:
在这里插入图片描述
这里.string “t” 只会占用2个字节,因此紧随其后的 “trigger_alignment” 会触发指令不对齐异常
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/15733.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高级运维开发工程师带你处理linux木马(挖矿病毒)实战例子

一、事态描述 centos7测试服务器,突然密码登不上去了,然后CPU占100%。已经猜到,登录密码过于简单,密码被破解挂马了。大概率是CPU挖矿病毒。 二、重置centos7登录root密码 步骤1 启动Linux Centos7系统,当出现如下画…

DevOps系列文章 之 Java使用jgit管理git仓库

最近设计基于gitops新的CICD方案,需要通过java读写git仓库,这里简单记录下。 在jgit中,存在最核心的三个组件:Git类,Repository类。Git类中包含了push commit之类的常见git操作,而Repository则实现了仓库的初始化和基…

使用黑盒测试在 Go 中重写 Bash 脚本

目录 前言: 开始 准备工作 描述行为:Bats 简介 行为描述:陷阱 描述行为:设计测试 重写:让我们开始用go吧! 重构和更新:实现胜利 结论 前言: 使用黑盒测试在Go中重写Bash脚本…

百度--搜索引擎是怎么实现的--如何制作一个搜索浏览器

1.搜索引擎是怎么实现的? 搜索引擎是通过以下步骤实现的: 网页抓取(Crawling):搜索引擎会使用网络爬虫(Web Crawler)自动地从互联网上抓取网页内容。爬虫按照一定的规则遍历网页并提取网页内容…

做题遇见的PHP函数汇总

mb_substr函数 mb_substr() 函数返回字符串的一部分,之前学过 substr() 函数,它只针对英文字符,如果要分割的中文文字则需要使用 mb_substr() 语法: mb_substr ( $str ,$start [, $length NULL [, $encoding mb_encoding() ]] …

docker中运行RabbitMq的启用插件指南

我们使用 Docker 来运行 RabbitMQ,有时需要启用一些插件,这个与正常安装的启用插件的步骤会有所不同。以下是在 Docker 中启用 RabbitMQ 插件的一般步骤: 首先,确认已经将 rabbitmq_delayed_message_exchange-3.12.0.ez 插件文件复…

adb: failed to install .\xxxxxx.apk: Failure [INSTALL_FAILED_USER_RESTRICTED

开发者模式和USB调试均已打开,adb安装时报错。看了一下,小米手机还需要开启USB安装才行。 问题已解决

《永劫无间》免费!《永劫无间》配置要求如何?

《永劫无间》于2021年7月8日开启不删档测试,8月12日在Steam全球公测,终于赶在两周年,2023年7月14日的炎炎夏日转为免费游戏。在《永劫无间》中,玩家可以选择不同的英雄,每个英雄都有独特的技能和风格,通过搜…

深入解析Redis的LRU与LFU算法实现

作者:vivo 互联网服务器团队 - Luo Jianxin 重点介绍了Redis的LRU与LFU算法实现,并分析总结了两种算法的实现效果以及存在的问题。 一、前言 Redis是一款基于内存的高性能NoSQL数据库,数据都缓存在内存里, 这使得Redis可以每秒轻…

【Python】Python项目打包发布(五)(制作Windows安装包)

Python项目打包发布汇总 【Python】Python项目打包发布(一)(基于Pyinstaller打包多目录项目) 【Python】Python项目打包发布(二)(基于Pyinstaller打包PyWebIO项目) 【Python】Pytho…

视图与索引的详细用法

视图与索引的详细用法 1.视图的主要作用包括:1.简化查询:2.数据安全性:3.数据抽象: 2.索引简介1.索引的作用主要有以下几个方面:1.快速定位数:2. 提高查询性能3.加速排序和连接操作4.维护数据完整性 3.索引…

从0开始学架构-架构的定义

从0开始学架构-架构的定义 文章目录 从0开始学架构-架构的定义系统与子系统模块与组件框架与架构软件框架(Software framework)软件架构区别 重新定义架构:4R 架构软件架构重新定义 三组容易混淆的概念: 系统与子系统模块与组件框…