1
0
mirror of https://github.com/rcore-os/rCore.git synced 2024-11-22 16:16:16 +04:00
rCore/docs/2_OSLab/g2/overview.md
2018-12-31 22:51:13 +08:00

8.4 KiB
Raw Blame History

概述

Raspberry Pi 简介

本实验的目标是将 RustOS 移植到 Raspberry Pi 3 Model B+ 上。其主要硬件参数如下:

Raspberry Pi 3B+
指令集 ARMv8-A 32/64 bit
片上系统(SoC) Broadcom BCM2837B0
处理器(CPU) 4 x Cortex-A53 1.4Ghz
图形处理器(GPU) Broadcom VideoCore IV
内存 1GB (与 GPU 共享)

ARMv8 架构简介

运行状态

根据寄存器位数的不同ARMv8 架构定义了两种运行状态(Execution States),分别为 AArch64AArch32。两种运行状态使用的指令集也不相同。RustOS 实现的是 AArch64。

异常级别

在 AArch64 下,可在 4 个异常级别(Exception level)中运行,分别为:

  • EL0: Normal user applications.
  • EL1: Operating system kernel typically described as privileged.
  • EL2: Hypervisor.
  • EL3: Secure monitor.

级别越高,特权(privilege)越高。一般称 EL0 为非特权级(unprivileged),其他的为特权级(unprivileged)。

寄存器

通用寄存器

AArch64 有 31 个 64 位通用寄存器(General-purpose registers) X0~X30,每个 64 位寄存器都有一个 32 位的版本 W0~W30。寄存器的使用规范一般如下:

  • 参数寄存器 (Argument registers, X0~X7):作为函数调用时的参数,返回值保存在 X0
  • 调用者保存寄存器(Caller-saved temporary registers, X9~X15):在函数调用前,如果调用者需要保护这些寄存器中的值直到函数调用之后,则调用者需要将它们保存到当前栈帧上,而被调用者可直接使用而不必保存与恢复;
  • 被调用者保存寄存器(Callee-saved registers, X19~X29):在函数调用中,如果该函数需要修改这些寄存器,则需要在函数开始执行前将它们保存到当前栈帧上,并在返回时恢复它们。
  • 帧指针寄存器(Frame point register, FPX29):用于保存当前函数的栈帧指针;
  • 链接寄存器(Link register, LRX30):用于保存函数返回的地址,执行 ret 指令会跳转到 LR

特殊寄存器

AArch64 有下列特殊寄存器(Special-purpose registers)

  • 零寄存器(Zero register, ZR):被映射为立即数 0可分别用 WZR/XZR 访问 32/64 位版本;
  • 程序计数器(Program counter, PC)当前指令的地址64 位;
  • 栈指针(Stack pointer, SP)当前栈顶地址64 位。在每个异常级别下都有一个栈指针,分别为 SP_EL0SP_EL1SP_EL2SP_EL3,直接访问 SP 时会根据当前异常级别自动选择对应的(如果 SPSel = 0,则在任何异常级别下都使用 SP_EL0)
  • 异常链接寄存器(Exception Link Register, ELR):用于保存异常返回的地址,在异常级别 1~3 下分别为 ELR_ELx,执行 eret 指令进行异常返回时会根据当前异常级别跳转到相应的 ELR
  • 保存的进程状态寄存器(Saved Process Status Register, SPSR):用于保存异常发生时的进程状态(PSTATE),在异常级别 1~3 下分别为 SPSR_ELx。执行 eret 指令进行异常返回时会根据当前异常级别,从相应的 SPSR 恢复进程状态。

进程状态

进程状态(Process state, PSTATE)是当前进程状态信息的抽象。AArch64 提供了一系列特殊寄存器来独立访问 PSTATE 中的每个字段,常用的几个如下(完整的字段描述参见 ARMv8 Reference Manual D1.7 节)

  • 条件标志位(Condition flags, NZCV)

    • N: Negative Condition flag
    • Z: Zero Condition flag
    • C: Carry Condition flag
    • V: oVerflow Condition flag
  • 异常屏蔽位(exception masking bits, DAIF)

    • D: Debug exception mask bit
    • A: SError interrupt mask bit
    • I: IRQ interrupt mask bit
    • F: FIQ interrupt mask bit
  • 当前异常级别(Current Exception level, CurrentEL):获取当前的异常级别;

  • 栈指针选择(Stack Pointer Select, SPSel):如果为 1则在不同异常级别下分别使用相应的 SP_ELx 作为 SP,否则任何时候都使用 SP_EL0 作为 SP

当异常发生时,当前的 PSTATE 会根据进入哪个异常级别保存到相应的 SPSR_ELx 中。

系统寄存器

可以通过系统寄存器(System registers)来进行 AArch64 的系统配置。一般每种系统寄存器在不同异常级别下都有相应的版本,用后缀 _ELx 表示。下表列出了常用的几个系统寄存器(全部系统寄存器参见 ARMv8 Reference Manual D12.1 节)

系统寄存器_ELx 名称 描述
CTR Cache Type Register 获取 cache 信息
ESR Exception Syndrome Register 保存发生异常的原因
FAR Fault Address Register 保存发生访存错误的虚拟地址
HCR Hypervisor Configuration Register 配置 EL2 下的虚拟化
MAIR Memory Attribute Indirection Register 配置内存属性
MPIDR Multiprocessor Affinity Register 多核系统中核的编号
SCTLR System Control Register 提供对内存系统等系统配置
TCR Translation Control Register 配置地址翻译系统的参数
TTBR0/TTBR1 Translation Table Base Register 设置翻译表(页表)基址
VBAR Vector Based Address Register 设置异常向量基址

对系统寄存器(包括部分特殊寄存器)的访问需要使用 mrsmsr 指令:

  • 读:

    mrs x0, TTBR0_EL1
    
  • 写:

    msr TTBR0_EL1, x0
    

crate aarch64regs 模块封装了对部分系统寄存器的访问。

SIMD/FP 寄存器

共有 32 个最高为 128 位的 SIMD/floating-point 寄存器,可分别通过 Q0~Q31D0~D31S0~S31H0~H31B0~B31 访问其 128、64、32、16、8 位版本。

使用这些寄存器需要 NEON 技术的支持。为了方便,在 RustOS 中禁用了 NEON (Cargo features +a53,+strict-align,-neon),这样在处理异常时无需保存这些寄存器。

官方文档

其他参考