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

树莓派简单操作系统制作之四:关于异常等级

目录

  • 背景
  • 信息打印
  • 异常等级切换实现
    • 等级切换
    • 代码实现
      • 打印异常等级

背景

上一小节中介绍了树莓派上输出的第一个裸机程序“Hello, world!”。本节内容将了解并介绍怎么配置正确的异常等级(exception level),关于异常等级的介绍可以参考:AArch64 异常等级(exception level)。以上介绍了通常操作系统运行在EL1等级,所以我们本节也会将操作系统切换到EL1。
基于前面的介绍可以实现uart驱动,并通过串口可以和系统交互。

信息打印

由于后面系统的打印会越来越多,所以我们需要实现通用的printf接口,printf是开源代码,避免做无意义的函数实现,这里我们直接拿来用了,这样我们就能轻松实现变量或者指定地址内容的打印,方便系统调试。
实现printf的api, 需要我们实现putc函数,以完成printf函数的初始化。putc函数主要调用我们上一节中实现的uart_send_char函数,具体内容如下

关于print的代码实现可以看本文所涉及的源代码,放在文章末尾处。

异常等级切换实现

系统上电后默认会进入EL3或者EL2(我本地的板子进入到了EL2,与板子早期初始化有关)。

等级切换

如AArch64 异常等级(exception level)文章中介绍,aarch64架构为实现等级管理,出于功能安全上的考虑,程序无法主动提高自己的异常等级,除非发生异常,类似我们通用的linux操作系统,用户空间(EL0)的程序无法主动进入内核空间(EL1),但当系统除以0,软件中断,访问非法地址等异常发生时,会进入更高的异常等级,执行相应的异常处理函数。
另外,arch64的指令集提供了svc命令,主动产生异常,进入更高异常等级。

异常发生后系统通常会有一下几个动作(假设异常发生在EL0):

  1. 当前指令位置保存到elr_el0寄存器。
  2. 当前处理器的状态保存在spsr_el0寄存器中。
  3. 保存其它寄存器,比如通用寄存器的值。
  4. 执行EL1中的异常处理程序,程序最终调用eret返回到EL0,同时恢复EL0程序中的上下文如x0-x30等寄存器。
  5. EL0处理器从spsr_el0寄存器中恢复处理器的状态,并在elr_el0寄存器保存的地址开始恢复执行。
    其它异常等级程序运行时发生异常也是这个过程,比如EL1的程序发生异常就会跳转到EL2执行异常处理程序,并最终返回EL1

实际上的系统大致是这么过程。实际实现中,elr_el0寄存器和spsr_el0寄存器,都可被更高异常等级执行的异常处理函数修改。根据这一特性可以实现高异常等级切换到更低异常等级,并指定低异常等级执行的程序位置和处理器状态。

代码实现

打印异常等级

要想实现异常等级的切换,首先需要确认程序所处的异常等级,所以首先需要一个可以打印异常等级的函数。
在aarch64架构中,存在CurrentEL变量保存异常等级信息,且每个异常等级都有权访问,因此可以通过以下汇编代码实现异常等级读取功能

.global get_el
    get_el:
        mrs x0, CurrentEL
        lsr x0, x0, #2
        ret

上诉代码实现的主要功能是将CurrentEL寄存器的值读取到x0通用寄存器中,并右移两位(CurrentEL前两位为空,没有意义,异常等级保存在第3,4位),之后函数返回x0的内容。
调用方法也非常简单,如下

imt el = get_el();

待续 。。。
在这里插入图片描述

http://www.dtcms.com/a/40766.html

相关文章:

  • 51c嵌入式~电路~合集13
  • 深度学习-135-LangGraph之应用实例(四)构建RAG问答系统同时对文档进行元数据增强
  • 游戏开发微信小程序--工具箱之父
  • 基于javaweb的SSM+Maven鲜花商城管理系统设计和实现(源码+文档+部署讲解)
  • Qt for Android下QMessageBox背景黑色、文字点击闪烁
  • 深入探讨Ceph:分布式存储架构的未来
  • 类和对象——拷贝对象时的一些编译器优化
  • AI绘画软件Stable Diffusion详解教程(3):Windows系统本地化部署操作方法(通用版)
  • Mybatis的分页插件
  • 视频级虚拟试衣技术在淘宝的产品化实践
  • 【Linux基础】Linux下的C编程指南
  • HAL库之是stm32cubemx安装
  • 定义数组存储3部汽车对象(class1)
  • 解决“ReadTimeoutError:HTTPSConnectionPool”pip安装超时问题
  • win11编译pytorch cuda128版本流程
  • wav格式的音频压缩,WAV 转 MP3 VBR 体积缩减比为 13.5%、多个 MP3 格式音频合并为一个、文件夹存在则删除重建,不存在则直接建立
  • 笔记:大模型Tokens是啥?为啥大模型按Tokens收费?
  • PyQt5入门教程和简单使用
  • Pandas在爬虫中的应用:快速清洗和存储表格数据
  • 【北京迅为】itop-3568 开发板openharmony鸿蒙烧写及测试-第2章OpenHarmony v3.2-Beta4版本测试
  • js逆向常用代码
  • 使用 Polars 进行人工智能医疗数据分析(ICU数据基本测试篇)
  • 毛泽东思想“活的灵魂”
  • 黑马Java面试教程_P5_微服务
  • ISO 15118,最新版,汽车充电桩相关标准,1~22子标准
  • Postman 11.34 最新版安装与API测试入门教程(Windows平台)
  • 释放 Cursor 的全部潜能:快速生成智能 Cursor Rules
  • Linux中子线程会继承父线程对相关变量的可见性
  • redis --- 相关基础知识整理
  • RNN,LSTM,GRU三种循环网络的对比