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

news2024/9/20 22:08:37

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

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

源码:

#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_hang

proc_hang: 
	b 	proc_hang

master:
        /* 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_EL3
	b.eq el3_entry
	//否则调用EL2的处理
	b el2_entry

el3_entry:
	eret

el2_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_FLAGS
	msr hcr_el2, x0
	//EL1页表还未建立,因此需要关闭MMU
	ldr x0, =SCTLR_VALUE_MMU_DISABLED
	msr 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_EL1
	msr spsr_el2, x0
   /*PC相对地址加载指令,将el1的入口函数地址赋值给x0寄存器,这里注意和adrp的区别,adrp返回的地址是4K对齐,这样的话就不是函数的地址了*/
	adr x0, el1_entry
	/*将x0寄存器赋值给elr_el2,这里是设置el2的异常返回地址*/
	msr elr_el2, x0
    /*el2异常返回,程序流程会进入到el1*/
	eret

el1_entry:
	bl print_el

	/* 设置异常向量表基地址到vbar寄存器 */
	ldr     x5, =vectors
	msr     vbar_el1, x5
	isb
	//bss段清零
	adr	x0, _bss
	adr	x1, _ebss
	sub	x1, x1, x0
	bl 	memzero

	/*预留栈空间*/
	mov	sp, #LOW_MEMORY 
	/*跳转到C函数*/
	bl	kernel_main
	b 	proc_hang		// should never come here

print_el:
    //先保存LR寄存器,保存子程序的返回地址,避免被破坏
	mov x10, x30

	/*
	   print EL
	 */
	adrp x0, el_string1
	add x0, x0, :lo12:el_string1
	bl put_string_uart

	mrs x5, CurrentEL
	/* get the currentEL value */
	/*CurrentEL寄存器的 [2:3] 保存的是当前异常等级,因此这里右移2位后赋值给x2寄存器*/
	lsr x2, x5, #2
	//48指的是ASCII码为0
	mov x0, #48
	// ‘0’ + 具体的EL值,得到相应EL等级的ASCII码
	add x0, x0, x2
	// 将x0(EL具体值)作为入参传达给串口打印出来
	bl put_uart
	/* print the new line tab */
	//打印换行符
	mov x0, #10
	bl put_uart
    //恢复LR寄存器
	mov x30, x10
	ret

异常向量表的实现:

#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 7
	b \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_invalid
	vtentry el1_irq_invalid
	vtentry el1_fiq_invalid
	vtentry el1_error_invalid

	/* Current EL with SPx
	   当前系统运行在EL1时使用EL1的栈指针SP
	   这说明系统在内核态发生了异常

	   Note: 我们暂时只实现IRQ中断
	 */
	vtentry el1_sync_invalid
	vtentry el1_irq_invalid
	vtentry el1_fiq_invalid
	vtentry el1_error_invalid

	/* Lower EL using AArch64
	   在用户态的aarch64的程序发生了异常
	 */
	vtentry el0_sync_invalid
	vtentry el0_irq_invalid
	vtentry el0_fiq_invalid
	vtentry el0_error_invalid

	/* Lower EL using AArch32
	   在用户态的aarch32的程序发生了异常
	 */
	vtentry el0_sync_invalid
	vtentry el0_irq_invalid
	vtentry el0_fiq_invalid
	vtentry el0_error_invalid

el1_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_ERROR

string_test:
	.string "t"

.global trigger_alignment
trigger_alignment:
	ldr x0, =0x80002
	ldr x1, [x0]
	ret

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学无止境·MySQL(4-3)(多表查询加强版-------更新版)

比4-2表中多几个数据,更具备普遍性 试题2(更新加强版)1、创建表2、找出销售部门中年纪最大的员工的姓名3、求财务部门最低工资的员工姓名4、列出每个部门收入总和高于9000的部门名称5、求工资在7500到8500元之间,年龄最大的人的姓…

MySql 高级-0706

1. MySQL 架构 1.1 MySQL 简介 mysql内核 sql优化攻城狮 mysql服务器的优化 各种参数常量设定 查询语句优化 主从复制 软硬件升级 容灾备份 sql编程 1.2 MySQL逻辑架构介绍 1.2.1第1层:连接层 ** 系统(客户端)访问 MySQL 服务器前,做的第一件事就是建立 TCP 连接…

HTML <map> 标签

实例 带有可点击区域的图像映射: <img src="planets.jpg" border="0" usemap="#planetmap" alt="Planets" /><map name="planetmap" id="planetmap"><area shape="circle" coords=&q…

多元分类预测 | Matlab 粒子群算法(PSO)优化xgboost的分类预测,多输入单输出模型。PSO-xgboost分类预测模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab 粒子群算法(PSO)优化xgboost的分类预测,多输入单输出模型。PSO-xgboost分类预测模型 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,程…

利用Python构建科学的交易系统:以趋势为例

在股票市场中&#xff0c;趋势被认为是一个非常重要的概念。趋势可以通过股票的价格、交易量等指标来确定。如果一只股票的价格在持续上涨&#xff0c;那么我们可以认为该股票处于上升趋势&#xff1b;反之&#xff0c;如果一只股票的价格在持续下跌&#xff0c;那么我们认为该…

物理机到容器的发展历程

物理机到容器的发展历程 物理主机虚拟化技术什么是虚拟化&#xff1f;虚拟化分类主流的虚拟化技术KVMLXC 容器Docker与Containerd容器编排为什么要编排工具容器编排工具有哪些&#xff1f; 物理主机 从传统的物理服务到现如今的云服务的发展离不开应用服务的拆分&#xff0c;由…

PDF怎么转长图?这四个方法免费好用!

记灵在线工具怎么转PDF为长图&#xff1f;PDF文件是一种常见的文档格式&#xff0c;它可以在不同的设备和操作系统上保持格式的一致性。然而&#xff0c;有时候我们需要将PDF文件转换成长图&#xff0c;以便于在社交媒体上分享或者在网站上展示。本文将介绍如何使用记灵在线工具…

110、基于51单片机智能浇花浇水系统土壤湿度检测温度自动灌溉报警设计(程序+原理图+PCB源文件+原理图讲解+参考论文+开题报告+程序流程图+元器件清单等)

选题背景及意义 在中国广大面积的农村&#xff0c;没有发达的工商业&#xff0c;有的只是大量闲置的田地。如果利用这些闲置的田地&#xff0c;种植美丽的花卉、树苗&#xff0c;能给当地带来一笔可观的收入。而这些花卉及树苗的种植对土壤湿度&#xff0c;温度有着极高的要求…

RTOS任务切换过程中堆栈的使用情况

我们知道 Cortex-M3 系列单片机内部有双堆栈机制。即 Cortex‐M3 拥有两个堆栈指针&#xff1a;主堆栈&#xff08;MSP&#xff09;和进程堆栈&#xff08;PSP&#xff09;。任一时刻只能使用其中的一个。通过控制寄存器 CONTROL 中的选择位进行控制。 两个堆栈指针如下&#…

CentOS环境下的Maven安装

CentOS 安装 Maven 镜像地址 镜像地址&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/apache/maven/ 下载地址&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.8.8/binaries/ 下载maven 将下载好的压缩包拷贝到根目录下 解压 tar -zxvf ap…

硬件性能 - 掌握内存知识

简介 本文章主要介绍了内存的基本知识&#xff0c;简单的判断内存是否耗尽、是否出现内存泄漏等问题。其他硬件性能分析如下&#xff1a; 1. 硬件性能 - CPU瓶颈分析 2. 硬件性能 - 磁盘瓶颈分析 3. 硬件性能 - 网络瓶颈分析 目录 1. 内存的定义 1.1. 内存的基本概念 1.2. 内…

Coggle 30 Days of ML (23年7月)任务二:数据可视化

Coggle 30 Days of ML (23年7月&#xff09;任务二&#xff1a;数据可视化 任务二&#xff1a;对数据集字符进行可视化&#xff0c;统计标签和字符分布 说明&#xff1a;在这个任务中&#xff0c;需要使用Pandas库对数据集的字符进行可视化&#xff0c;并统计数据集中的标签和…

【JavaEE】Servlet 中常用API有哪些?前后端交互方式有哪些?

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE初阶 目录 一、Servlet 运行原理 二、Servlet常用API 2.1 HttpServlet&#xff08;抽象类&#xff09; 2.1.1. init 方法 2.1.2 service方法 2.1.3 destroy方法 三、HttpServletRequest 3.1 Ht…

如何自动(定时/间隔/重复)执行 同步文件、备份打包加密压缩文件

参考下列两个教程结合使用即可&#xff1a; 快捷自由定时重启、注销、关机、文件夹同步打开程序等 如何从多个文件夹内转移全部文件&#xff08;忽略文件夹的结构&#xff09;&#xff08;进行复制&#xff09;&#xff08;再打包&#xff09; 就是先设定好 勾选对 来源路径’…

JavaScript基础知识巩固

JavaScript基础 输入输出语法 输出&#xff1a; document.write(要输出的内容) alert(页面弹出警告窗) console.log(控制台打印)输入&#xff1a; let value prompt(用户输入的内容)变量的本质 是程序在内存中申请的一块用来存放数据的空间变量命名规范 不能用关键字 关键…

deeplabv3+源码之慢慢解析根目录(1)main.py--get_argparser函数

系列文章目录&#xff08;更新中&#xff09; 第一章deeplabv3源码之慢慢解析根目录(1)main.py–get_argparser函数 第一章deeplabv3源码之慢慢解析根目录(2)main.py–get_dataset函数 第一章deeplabv3源码之慢慢解析根目录(3)main.py–validate函数 第一章deeplabv3源码之慢慢…

王学岗机载开发(一)———————系统配置

1&#xff0c;安装VMware Workstation&#xff0c;然后安装虚拟机 VMware下载地址 Ubuntu镜像 2&#xff0c; 点击虚拟机&#xff0c;设置按钮 选择处理器&#xff0c;勾选虚拟化Intel VT-x/EPT或AMD-V/RVI(V)选项(因为我们是再虚拟机里跑虚拟机) 3&#xff0c;Linux的交换分区…

Django搭建图书管理系统04:View视图初探

数据库虽然已经有了&#xff0c;但是用户通常只需要这个庞大数据库中的很小一部分进行查看、修改等操作。为此还需要代码来恰当的取出并展示数据&#xff0c;这一部分代码就被称为视图。 Django 中视图的概念是**「一类具有相同功能和模板的网页的集合」**。 Hello World! 首…

SpringBoot—统一功能处理

SpringBoot—统一功能处理 &#x1f50e;小插曲(通过一级路由调用多种方法)&#x1f50e;使用拦截器实现用户登录权限的统一校验自定义拦截器将自定义拦截器添加至配置文件中拦截器的实现原理统⼀访问前缀添加 &#x1f50e;统一异常的处理&#x1f50e;统一数据格式的返回统一…

linux中grep命令的常见用法

作为linux中最为常用的三大文本&#xff08;awk&#xff0c;sed&#xff0c;grep&#xff09;处理工具之一&#xff0c;掌握好其用法是很有必要的。 首先谈一下grep命令的常用格式为&#xff1a;grep [选项] ”模式“ [文件] grep家族总共有三个&#xff1a;grep&#xff…