跳转至

畅想未来——仿真处理器优化进阶

这个方向的实验是基于仿真进一步完善片上系统的功能,包括了很多我们在实验中提及但并未真正实现的内容。

1 特权与异常 XproMAX(硬件方向)

在真正的片上系统里,ecall——系统调用异常仅仅是最简单的异常之一,为了支持片上系统的更多功能,我们需要对特权和异常架构进行进一步的完善,包括:

  • 特权级转换:RISCV提供了4个特权级,一般而言操作系统会运行在S模式,用户程序运行在U模式,而访问外设的驱动程序则运行在M模式,为了保证安全,我们需要在特权级之间进行转换,这就需要对特权级转换的指令进行支持。你需要参考RISCV的特权架构手册,按照你对片上系统的理解来完善特权级转换的操作(注意,这里并不需要你完全按照RISCV的完备描述来设计特权系统)

  • 更多的异常处理:RISCV定义了许多类型的异常,其中不乏和操作系统启动息息相关的异常,包括:

    • 访存地址非对齐异常:当load/store指令访问的地址并非粒度对齐(例如对末尾位3的地址进行半字读取)时,会触发该异常。

    • 指令非法异常:当用户程序访问了不支持的指令时,会触发该异常。

    • 特权级异常:当用户程序访问了不支持的特权级指令(例如在U模式下运行了CSR读写指令)时,会触发该异常。

    你需要实现这些异常中至少4个异常,并编写对应的测试用例进行测试。

完成了这些任务之后,你仍然需要启动课程提供的操作系统,但现在的操作系统应当能支持基本的特权级转换,以及异常处理。

2 操作系统进阶——进程调度(软件方向)

我们为大家提供了一个相当简易的操作系统,同时也为大家的操作系统开发提供了一定的自由度。一个较为完备的操作系统需要支持多道程序,而我们的操作系统目前仅仅能够通过user_naive_load函数向一个固定地址加载一个用户程序——这显然是不够的。为此,你需要对操作系统进行进一步的完善,包括:

  • 将多个应用程序同时放入内存的不同位置:操作系统中已经提供了user_ctx_load和kernel_ctx_load两个加载函数,你可以借助这两个函数的,也可以重新设计函数,来将用户程序和内核程序加载到不同的内存位置。如果你选择使用我们提供的函数,那么可能会需要一些时间来理解这两个函数的实现。

  • 设计进程信息块:在进程切换的过程中,上下文的记录是尤为重要的。操作系统中提供了一个PCB结构,用来保存上下文信息。你需要利用这个结构体,通过设计数据结构来保存多个进程的上下文信息,以便在进程切换的时候能够正确地保存和恢复上下文。

  • 进程调度:为简单起见,你可以实现一个主动放弃CPU的简单调度器(也就是说是否放弃CPU由程序通过主动调用yield函数来实现)。你需要完善SYS_YIELD系统调用,使得用户程序能够通过调用yield函数来主动放弃CPU,从而实现多道程序的调度。

在这个实验中,我们最低要求大家实现一个内核进程+一个用户进程的调度,但你可以自行设计数据结构,使得你的操作系统能够支持更多的进程。我们希望大家能够结合操作系统课程和本课程的知识,通过对本课程处理器特点的理解(例如对于访存原理的理解),设计出性能较好的进程调度算法。