制作一个RISC-V的操作系统十六-系统调用

ops/2025/2/9 4:45:59/

文章目录

  • 用户态和内核态
  • mstatus设置
  • 模式切换
  • 核心流程
  • 封装
  • 代码
    • 背景解释
    • 代码示例解析
    • 解释
    • 目的

用户态和内核态

在这里插入图片描述

mstatus设置

此时UIE设置为1和MPIE为1,MPP设置为0
代表当前权限允许UIE中断发生,并且在第一个mret后将权限恢复为用户态,同时MIE也保持开启
在这里插入图片描述

模式切换

ecall相当于一次触发异常,然后在对应的异常中去处理对应的系统调用
在这里插入图片描述

核心流程

  • 首先在进程中使用到gethartid函数
  • gethartid函数保存a7寄存器为调用号,然后ecall进行系统调用,ret再回到调用gethartid函数的下一条地址
  • ecall会触发中断进入trap_vector,此时的mepc是ecall地址,mecause是8
  • trap_vector会保存当前上下文,然后增加一个指向保存了的上下文的地址作为trap_hander的第三个参数,trap_hander结束后会将返回值写到mepc中,然后mret到mepc对应的位置,此时是ecall+4的地址
  • trap_hander中会执行syscall函数,参数是传入的之前刚开始保存了的上下文,然后syscall函数中的会对该上下文的a0寄存器赋值为hart的id
  • 此时,回到最后恢复保存的上下文的地方,也就是trap_vector那里,恢复上下文后,此时返回值正好是hart的id,然后mepc也被选择到了ecall+4,那么返回到上一级为gethartid的ret函数,此时返回值也是hart的id,即得到hartid
    在这里插入图片描述
    原则a6其实也可以作为参数
    在这里插入图片描述

封装

就是用户态使用的函数用到的头文件和内核态使用的函数用到的头文件建议分别封装到各个文件中,在用户态中的作为C库,内核态中的内核维护,如果头文件相关定义不一致可能会出现问题
在这里插入图片描述

代码

https://github.com/FULLK/risllkos/tree/main/Fullkenerl11

#ifdef CONFIG_SYSCALLli      t0, 0xffffffff          # Load the value 0xffffffff into register t0csrw    pmpaddr0, t0           # Write this value to the PMP address register 0li      t0, 0xf                 # Load the value 0xf (binary 1111) into register t0csrw    pmpcfg0, t0             # Write this value to the PMP configuration register 0
#endif

背景解释

在RISC-V架构中,PMP(Physical Memory Protection)是用于控制不同特权级别访问内存的能力的一个特性。它通过一系列配置寄存器(PMP配置寄存器如pmpcfg0)和地址寄存器(PMP地址寄存器如pmpaddr0)来定义内存区域的访问权限(读、写、执行)以及哪些特权模式可以访问这些区域。

代码示例解析

假设你正在开发一个RISC-V的操作系统,并且使用QEMU作为模拟器来测试你的代码。当你升级到QEMU 6.0及以上版本时,遇到了一个与PMP配置相关的问题:如果没有设置任何PMP条目,从Supervisor (S) 或 User (U) 模式进行的内存访问会导致异常。

解释

  • li t0, 0xffffffff: 这行代码将寄存器t0赋值为0xffffffff,这个值在32位地址空间中代表一个非常大的地址(几乎接近地址空间的最大值)。按照标准,这个值本意是用来设置PMP条目的上界地址,但由于一些QEMU实现细节,将其设置为全1时可能被解释为覆盖整个地址空间的特殊情况。

  • csrw pmpaddr0, t0: 此指令将寄存器t0的值写入到PMP地址寄存器0(pmpaddr0),试图设置PMP的第一个条目覆盖整个地址空间的访问权限。

  • li t0, 0xf: 这行代码设置寄存器t0为0xf,二进制形式为1111。在PMP配置中,每个位对应一个PMP条目的访问权限(读、写、执行),因此0xf意味着开启所有权限。

  • csrw pmpcfg0, t0: 最后,这行代码将寄存器t0的值写入到PMP配置寄存器0(pmpcfg0),激活了第一个PMP条目并设置了读、写、执行的权限。

目的

这段代码的主要目的是作为临时解决方案,确保即使在没有详细配置PMP条目的情况下,用户和监督模式下的程序也能正常访问内存,以避免在使用QEMU 6.0及以上版本时遇到的异常问题。它通过配置一个PMP条目来覆盖整个地址空间,并赋予所有访问权限,从而绕过了新版本QEMU对未配置PMP条目的严格检查。

在RISC-V架构中,PMP(Physical Memory Protection,物理内存保护)机制通过一系列配置寄存器来控制对物理内存的访问权限,以此增强系统的安全性。PMP寄存器分为地址寄存器(如pmpaddrN)和配置寄存器(如pmpcfgN),共同定义了多个内存访问控制区域。

当说“试图设置PMP的第一个条目覆盖整个地址空间的访问权限”时,这指的是通过编程PMP的地址和配置寄存器来创建一个PMP规则,这个规则旨在允许对整个物理地址空间执行读、写和执行操作,而不受任何访问限制。具体到代码示例:

  • li t0, 0xffffffff:这一行是装载指令,将立即数0xffffffff(即32位地址空间中的最大值减一)送入寄存器t0。在TOR(Top of Range)匹配模式下,PMP地址寄存器中的值通常表示区间的上界地址。理论上,全1的上界地址可能被解释为企图涵盖整个地址空间的意图,尽管实际上因为地址对齐和边界处理,它可能无法精确覆盖到地址空间的最后一个字节。

  • csrw pmpaddr0, t0:这条指令将t0寄存器中的值写入到PMP地址寄存器0(pmpaddr0),试图设置PMP的第一个条目的上界地址。

  • li t0, 0xfcsrw pmpcfg0, t0:这两行是配置PMP条目的权限。0xf(十六进制)等于二进制的1111,分别代表了读®、写(W)、执行(X)和开启(L)权限位。通过写入到pmpcfg0,为PMP条目0设置了全权限。

然而,根据RISC-V的PMP规范,单个PMP条目通常不能直接覆盖整个地址空间,特别是在TOR模式下,pmpaddr0寄存器存储的是第一个区间的上界物理地址的高32位,即使设置为全1,也无法完美覆盖到地址空间的最末尾。而且,如之前讨论中提及的,QEMU的特定实现方式可能使得pmpaddr0 = 0xffffffff在某些情境下被特殊处理,看似覆盖了整个地址空间。


http://www.ppmy.cn/ops/28844.html

相关文章

LabVIEW换智能仿真三相电能表研制

LabVIEW换智能仿真三相电能表研制 在当前电力工业飞速发展的背景下,确保电能计量的准确性与公正性变得尤为重要。本文提出了一种基于LabVIEW和单片机技术,具有灵活状态切换功能的智能仿真三相电能表,旨在通过技术创新提高电能计量人员的培训…

数据库索引(Mysql)

简述:数据库索引是加速数据检索,提高查询效率的一种数据结构 语法规则 创建索引 --通用语法规则 --[内容] 可选参数 --UNIQUE: 可选关键字,用于创建唯一索引,确保索引列的值是唯一的 CREATE [UNIQUE] INDEX 索引名 ON 表名(字段名,...) [ASC | DESC];…

CACTER AI实验室:AI大模型在邮件安全领域的应用

随着人工智能技术的飞速发展,AI已经深入到生活的各个领域。AI大模型在邮件安全领域展现出巨大潜力,尤其是反钓鱼检测上的应用,正逐渐展现出其独特的价值。 4月24日,CACTER AI实验室高级产品经理刘佳雄在直播交流会上分享了CACTER …

【Kotlin】Channel简介

1 前言 Channel 是一个并发安全的阻塞队列,可以通过 send 函数往队列中塞入数据,通过 receive 函数从队列中取出数据。 当队列被塞满时,send 函数将被挂起,直到队列有空闲缓存;当队列空闲时,receive 函数将…

用js代码实现贪吃蛇小游戏

js已经学了大部分了,现在就利用我所学的js知识试试做贪吃蛇小游戏吧 以下部分相关图片以及思路笔记均出自渡一陈老师的视频 首先制作简单的静态页面,添加贪吃蛇移动的背景和相关图片,比如开始游戏等等 将各个功能均封装在函数中&#xff0…

45. UE5 RPG 使用元属性(Meta Attributes)以及使用Set by Caller修改伤害

在RPG游戏中,我们是不会直接修改生命值的属性,是因为在修改角色属性时,需要获取角色的属性并进行复杂的计算,所以,我们正常情况下使用元属性(Meta Attributes)作为计算的中间的媒。在服务器上先…

ipad的文件如何传到手机里 iPad较大文件怎么发送出去 iMazing下载教程

在现代生活中,随着移动设备的普及和多样化,我们经常需要在不同设备之间传输文件,以便在工作、学习或娱乐中更加便捷地使用这些文件。iPad和iPhone是用户广泛使用的设备,我们时常使用它们来存储和访问大量的个人数据。但有时&#…

Scala 第三篇 OOP篇

Scala 第三篇 OOP篇 上接:Scala 第二篇 算子篇 前序一、类 1、修饰符2、创建类示例3、类的继承 二、抽象类三、单例对象四、特质 1、动态混入2、抽象类 VS 特质 五、内部类六、样例类七、枚举八、泛型九、隐式类十、包与包对象练习 前序 1、Scala 为纯粹OOP 1.1、…