Documentation / translations / zh_CN / arch / riscv / boot.rst


Based on kernel version 6.12.4. Page generated on 2024-12-12 21:02 EST.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
.. SPDX-License-Identifier: GPL-2.0
.. include:: ../../disclaimer-zh_CN.rst

:Original: Documentation/arch/riscv/boot.rst

:翻译:

 龙进 Jin Long <longjin@dragonos.org>

========================
RISC-V内核启动要求和限制
========================

:Author: Alexandre Ghiti <alexghiti@rivosinc.com>
:Date: 23 May 2023

这份文档描述了RISC-V内核对引导加载程序和固件的期望,以及任何开发者在接触
早期启动过程时必须牢记的约束。在这份文档中, ``早期启动过程`` 指的是在最
终虚拟映射设置之前运行的任何代码。

内核预加载的要求和限制
======================

RISC-V内核对引导加载程序和平台固件有以下要求:

寄存器状态
----------

RISC-V内核期望:

  * ``$a0`` 应包含当前核心的hartid。
  * ``$a1`` 应包含内存中设备树的地址。

CSR 寄存器状态
--------------

RISC-V内核期望:

  * ``$satp = 0``: 如果存在MMU,必须将其禁用。

为常驻固件保留的内存
--------------------

RISC-V内核在直接映射中不能映射任何常驻内存或用PMPs保护的内存,
因此固件必须根据设备树规范 和/或 UEFI规范正确标记这些区域。

内核的位置
----------

RISC-V内核期望被放置在PMD边界(对于rv64为2MB对齐,对于rv32为4MB对齐)。
请注意,如果不是这样,EFI stub 将重定位内核。

硬件描述
--------

固件可以将设备树或ACPI表传递给RISC-V内核。

设备树可以直接从前一阶段通过$a1寄存器传递给内核,或者在使用UEFI启动时,
可以通过EFI配置表传递。

ACPI表通过EFI配置表传递给内核。在这种情况下,EFI stub 仍然会创建一个
小的设备树。请参阅下面的"EFI stub 和设备树"部分,了解这个设备树的详细
信息。

内核入口
--------

在SMP系统中,有两种方法可以进入内核:

- ``RISCV_BOOT_SPINWAIT``:固件在内核中释放所有的hart,一个hart赢
  得抽奖并执行早期启动代码,而其他的hart则停在那里等待初始化完成。这种
  方法主要用于支持没有SBI HSM扩展和M模式RISC-V内核的旧固件。
- ``有序启动``:固件只释放一个将执行初始化阶段的hart,然后使用SBI HSM
  扩展启动所有其他的hart。有序启动方法是启动RISC-V内核的首选启动方法,
  因为它可以支持CPU热插拔和kexec。

UEFI
----

UEFI 内存映射
~~~~~~~~~~~~~

使用UEFI启动时,RISC-V内核将只使用EFI内存映射来填充系统内存。

UEFI固件必须解析 ``/reserved-memory`` 设备树节点的子节点,并遵守设备
树规范,将这些子节点的属性( ``no-map`` 和 ``reusable`` )转换为其正
确的EFI等价物(参见设备树规范v0.4-rc1的"3.5.4/reserved-memory和
UEFI"部分)。

RISCV_EFI_BOOT_PROTOCOL
~~~~~~~~~~~~~~~~~~~~~~~

使用UEFI启动时,EFI stub 需要引导hartid以便将其传递给 ``$a1`` 中的
RISC-V内核。EFI stub使用以下方法之一获取引导hartid:

- ``RISCV_EFI_BOOT_PROTOCOL`` (**首选**)。
- ``boot-hartid`` 设备树子节点(**已弃用**)。

任何新的固件都必须实现 ``RISCV_EFI_BOOT_PROTOCOL``,因为基于设备树
的方法现已被弃用。

早期启动的要求和约束
====================

RISC-V内核的早期启动过程遵循以下约束:

EFI stub 和设备树
-----------------

使用UEFI启动时,EFI stub 会用与arm64相同的参数补充(或创建)设备树,
这些参数在Documentation/arch/arm/uefi.rst中的
"UEFI kernel supporton ARM"段落中有描述。

虚拟映射安装
------------

在RISC-V内核中,虚拟映射的安装分为两步进行:

1. ``setup_vm()`` 在 ``early_pg_dir`` 中安装一个临时的内核映射,这
   允许发现系统内存。   此时只有内核文本/数据被映射。在建立这个映射时,
   不能进行分配(因为系统内存还未知),所以``early_pg_dir``页表是静
   态分配的(每个级别只使用一个表)。

2. ``setup_vm_final()`` 在 ``swapper_pg_dir`` 中创建最终的内核映
   射,并利用发现的系统内存   创建线性映射。在建立这个映射时,内核可以
   分配内存,但不能直接访问它(因为直接映射还不存在),所以它使用fixmap
   区域的临时映射来访问新分配的页表级别。

为了让 ``virt_to_phys()`` 和 ``phys_to_virt()`` 能够正确地将直接
映射地址转换为物理地址,它们需要知道DRAM的起始位置。这发生在步骤1之后,
就在步骤2安装直接映射之前(参见arch/riscv/mm/init.c中的
``setup_bootmem()`` 函数)。在安装最终虚拟映射之前使用这些宏时必须
仔细检查。

通过fixmap进行设备树映射
------------------------

由于 ``reserved_mem`` 数组是用 ``setup_vm()`` 建立的虚拟地址初始化
的,并且与``setup_vm_final()``建立的映射一起使用,RISC-V内核使用
fixmap区域来映射设备树。这确保设备树可以通过两种虚拟映射访问。

Pre-MMU执行
-----------

在建立第一个虚拟映射之前,需要运行一些代码。这些包括第一个虚拟映射的安装本身,
早期替代方案的修补,以及内核命令行的早期解析。这些代码必须非常小心地编译,因为:

- ``-fno-pie``:这对于使用``-fPIE``的可重定位内核是必需的,否则,任何对
  全局符号的访问都将通过  GOT进行,而GOT只是虚拟地重新定位。
- ``-mcmodel=medany``:任何对全局符号的访问都必须是PC相对的,以避免在设
  置MMU之前发生任何重定位。
- *所有* 的仪表化功能也必须被禁用(包括KASAN,ftrace和其他)。

由于使用来自不同编译单元的符号需要用这些标志编译该单元,我们建议尽可能不要使用
外部符号。