<!DOCTYPE html>
<html lang="en" data-content_root="../../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>RISC-V Kernel Boot Requirements and Constraints — The Linux Kernel documentation</title>
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="../../_static/alabaster.css?v=3918102e" />
<script src="../../_static/documentation_options.js?v=5929fcd5"></script>
<script src="../../_static/doctools.js?v=9bcbadda"></script>
<script src="../../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
<link rel="next" title="Boot image header in RISC-V Linux" href="boot-image-header.html" />
<link rel="prev" title="ACPI on RISC-V" href="acpi.html" />
<link rel="stylesheet" href="../../_static/custom.css" type="text/css" />
</head><body>
<div class="document">
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../../index.html">
<img class="logo" src="../../_static/logo.svg" alt="Logo of The Linux Kernel"/>
</a></p>
<h1 class="logo"><a href="../../index.html">The Linux Kernel</a></h1>
<p class="blurb">6.18.50</p>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
<p>
<h3 class="kernel-toc-contents">Contents</h3>
<input type="checkbox" class="kernel-toc-toggle" id = "kernel-toc-toggle" checked>
<label class="kernel-toc-title" for="kernel-toc-toggle"></label>
<div class="kerneltoc" id="kerneltoc">
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../process/development-process.html">Development process</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../process/submitting-patches.html">Submitting patches</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../process/code-of-conduct.html">Code of conduct</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../maintainer/index.html">Maintainer handbook</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../process/index.html">All development-process docs</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../core-api/index.html">Core API</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../driver-api/index.html">Driver APIs</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../subsystem-apis.html">Subsystems</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../locking/index.html">Locking</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../process/license-rules.html">Licensing rules</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../doc-guide/index.html">Writing documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../dev-tools/index.html">Development tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../dev-tools/testing-overview.html">Testing guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../kernel-hacking/index.html">Hacking guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../trace/index.html">Tracing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../fault-injection/index.html">Fault injection</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../livepatch/index.html">Livepatching</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../rust/index.html">Rust</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../admin-guide/index.html">Administration</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../kbuild/index.html">Build system</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../admin-guide/reporting-issues.html">Reporting issues</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../tools/index.html">Userspace tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../userspace-api/index.html">Userspace API</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../firmware-guide/index.html">Firmware</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../devicetree/index.html">Firmware and Devicetree</a></li>
</ul>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal" href="../index.html">CPU architectures</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../arc/index.html">ARC architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../arm/index.html">ARM Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../arm64/index.html">ARM64 Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../loongarch/index.html">LoongArch Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../m68k/index.html">m68k Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../mips/index.html">MIPS-specific Documentation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../nios2/index.html">Nios II Specific Documentation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../openrisc/index.html">OpenRISC Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../parisc/index.html">PA-RISC Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../powerpc/index.html">powerpc</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="index.html">RISC-V architecture</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="acpi.html">ACPI on RISC-V</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">RISC-V Kernel Boot Requirements and Constraints</a></li>
<li class="toctree-l3"><a class="reference internal" href="boot-image-header.html">Boot image header in RISC-V Linux</a></li>
<li class="toctree-l3"><a class="reference internal" href="vm-layout.html">Virtual Memory Layout on RISC-V Linux</a></li>
<li class="toctree-l3"><a class="reference internal" href="hwprobe.html">RISC-V Hardware Probing Interface</a></li>
<li class="toctree-l3"><a class="reference internal" href="patch-acceptance.html">arch/riscv maintenance guidelines for developers</a></li>
<li class="toctree-l3"><a class="reference internal" href="uabi.html">RISC-V Linux User ABI</a></li>
<li class="toctree-l3"><a class="reference internal" href="vector.html">Vector Extension Support for RISC-V Linux</a></li>
<li class="toctree-l3"><a class="reference internal" href="cmodx.html">Concurrent Modification and Execution of Instructions (CMODX) for RISC-V Linux</a></li>
<li class="toctree-l3"><a class="reference internal" href="features.html">Feature status on riscv architecture</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../s390/index.html">s390 Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../sh/index.html">SuperH Interfaces Guide</a></li>
<li class="toctree-l2"><a class="reference internal" href="../sparc/index.html">Sparc Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="../x86/index.html">x86-specific Documentation</a></li>
<li class="toctree-l2"><a class="reference internal" href="../xtensa/index.html">Xtensa Architecture</a></li>
</ul>
</li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../staging/index.html">Unsorted documentation</a></li>
</ul>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../translations/index.html">Translations</a></li>
</ul>
</div>
<script type="text/javascript"> <!--
var sbar = document.getElementsByClassName("sphinxsidebar")[0];
let currents = document.getElementsByClassName("current")
if (currents.length) {
sbar.scrollTop = currents[currents.length - 1].offsetTop;
}
--> </script>
<div role="note" aria-label="source link">
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../../_sources/arch/riscv/boot.rst.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
</div>
</div>
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<div class="language-selection">
English
<ul>
<li><a href="../../translations/zh_CN/arch/riscv/boot.html">Chinese (Simplified)</a></li>
</ul>
</div>
<section id="risc-v-kernel-boot-requirements-and-constraints">
<h1>RISC-V Kernel Boot Requirements and Constraints<a class="headerlink" href="#risc-v-kernel-boot-requirements-and-constraints" title="Link to this heading">¶</a></h1>
<dl class="field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Alexandre Ghiti <<a class="reference external" href="mailto:alexghiti%40rivosinc.com">alexghiti<span>@</span>rivosinc<span>.</span>com</a>></p>
</dd>
<dt class="field-even">Date<span class="colon">:</span></dt>
<dd class="field-even"><p>23 May 2023</p>
</dd>
</dl>
<p>This document describes what the RISC-V kernel expects from bootloaders and
firmware, and also the constraints that any developer must have in mind when
touching the early boot process. For the purposes of this document, the
<code class="docutils literal notranslate"><span class="pre">early</span> <span class="pre">boot</span> <span class="pre">process</span></code> refers to any code that runs before the final virtual
mapping is set up.</p>
<section id="pre-kernel-requirements-and-constraints">
<h2>Pre-kernel Requirements and Constraints<a class="headerlink" href="#pre-kernel-requirements-and-constraints" title="Link to this heading">¶</a></h2>
<p>The RISC-V kernel expects the following of bootloaders and platform firmware:</p>
<section id="register-state">
<h3>Register state<a class="headerlink" href="#register-state" title="Link to this heading">¶</a></h3>
<p>The RISC-V kernel expects:</p>
<blockquote>
<div><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">$a0</span></code> to contain the hartid of the current core.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">$a1</span></code> to contain the address of the devicetree in memory.</p></li>
</ul>
</div></blockquote>
</section>
<section id="csr-state">
<h3>CSR state<a class="headerlink" href="#csr-state" title="Link to this heading">¶</a></h3>
<p>The RISC-V kernel expects:</p>
<blockquote>
<div><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">$satp</span> <span class="pre">=</span> <span class="pre">0</span></code>: the MMU, if present, must be disabled.</p></li>
</ul>
</div></blockquote>
</section>
<section id="reserved-memory-for-resident-firmware">
<h3>Reserved memory for resident firmware<a class="headerlink" href="#reserved-memory-for-resident-firmware" title="Link to this heading">¶</a></h3>
<p>The RISC-V kernel must not map any resident memory, or memory protected with
PMPs, in the direct mapping, so the firmware must correctly mark those regions
as per the devicetree specification and/or the UEFI specification.</p>
</section>
<section id="kernel-location">
<h3>Kernel location<a class="headerlink" href="#kernel-location" title="Link to this heading">¶</a></h3>
<p>The RISC-V kernel expects to be placed at a PMD boundary (2MB aligned for rv64
and 4MB aligned for rv32). Note that the EFI stub will physically relocate the
kernel if that’s not the case.</p>
</section>
<section id="hardware-description">
<h3>Hardware description<a class="headerlink" href="#hardware-description" title="Link to this heading">¶</a></h3>
<p>The firmware can pass either a devicetree or ACPI tables to the RISC-V kernel.</p>
<p>The devicetree is either passed directly to the kernel from the previous stage
using the <code class="docutils literal notranslate"><span class="pre">$a1</span></code> register, or when booting with UEFI, it can be passed using the
EFI configuration table.</p>
<p>The ACPI tables are passed to the kernel using the EFI configuration table. In
this case, a tiny devicetree is still created by the EFI stub. Please refer to
“EFI stub and devicetree” section below for details about this devicetree.</p>
</section>
<section id="kernel-entry">
<h3>Kernel entry<a class="headerlink" href="#kernel-entry" title="Link to this heading">¶</a></h3>
<p>On SMP systems, there are 2 methods to enter the kernel:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">RISCV_BOOT_SPINWAIT</span></code>: the firmware releases all harts in the kernel, one hart
wins a lottery and executes the early boot code while the other harts are
parked waiting for the initialization to finish. This method is mostly used to
support older firmwares without SBI HSM extension and M-mode RISC-V kernel.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Ordered</span> <span class="pre">booting</span></code>: the firmware releases only one hart that will execute the
initialization phase and then will start all other harts using the SBI HSM
extension. The ordered booting method is the preferred booting method for
booting the RISC-V kernel because it can support CPU hotplug and kexec.</p></li>
</ul>
</section>
<section id="uefi">
<h3>UEFI<a class="headerlink" href="#uefi" title="Link to this heading">¶</a></h3>
<section id="uefi-memory-map">
<h4>UEFI memory map<a class="headerlink" href="#uefi-memory-map" title="Link to this heading">¶</a></h4>
<p>When booting with UEFI, the RISC-V kernel will use only the EFI memory map to
populate the system memory.</p>
<p>The UEFI firmware must parse the subnodes of the <code class="docutils literal notranslate"><span class="pre">/reserved-memory</span></code> devicetree
node and abide by the devicetree specification to convert the attributes of
those subnodes (<code class="docutils literal notranslate"><span class="pre">no-map</span></code> and <code class="docutils literal notranslate"><span class="pre">reusable</span></code>) into their correct EFI equivalent
(refer to section “3.5.4 /reserved-memory and UEFI” of the devicetree
specification v0.4-rc1).</p>
</section>
<section id="riscv-efi-boot-protocol">
<h4>RISCV_EFI_BOOT_PROTOCOL<a class="headerlink" href="#riscv-efi-boot-protocol" title="Link to this heading">¶</a></h4>
<p>When booting with UEFI, the EFI stub requires the boot hartid in order to pass
it to the RISC-V kernel in <code class="docutils literal notranslate"><span class="pre">$a1</span></code>. The EFI stub retrieves the boot hartid using
one of the following methods:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">RISCV_EFI_BOOT_PROTOCOL</span></code> (<strong>preferred</strong>).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">boot-hartid</span></code> devicetree subnode (<strong>deprecated</strong>).</p></li>
</ul>
<p>Any new firmware must implement <code class="docutils literal notranslate"><span class="pre">RISCV_EFI_BOOT_PROTOCOL</span></code> as the devicetree
based approach is deprecated now.</p>
</section>
</section>
</section>
<section id="early-boot-requirements-and-constraints">
<h2>Early Boot Requirements and Constraints<a class="headerlink" href="#early-boot-requirements-and-constraints" title="Link to this heading">¶</a></h2>
<p>The RISC-V kernel’s early boot process operates under the following constraints:</p>
<section id="efi-stub-and-devicetree">
<h3>EFI stub and devicetree<a class="headerlink" href="#efi-stub-and-devicetree" title="Link to this heading">¶</a></h3>
<p>When booting with UEFI, the devicetree is supplemented (or created) by the EFI
stub with the same parameters as arm64 which are described at the paragraph
“UEFI kernel support on ARM” in <a class="reference internal" href="../arm/uefi.html"><span class="doc">The Unified Extensible Firmware Interface (UEFI)</span></a>.</p>
</section>
<section id="virtual-mapping-installation">
<h3>Virtual mapping installation<a class="headerlink" href="#virtual-mapping-installation" title="Link to this heading">¶</a></h3>
<p>The installation of the virtual mapping is done in 2 steps in the RISC-V kernel:</p>
<ol class="arabic simple">
<li><p><code class="docutils literal notranslate"><span class="pre">setup_vm()</span></code> installs a temporary kernel mapping in <code class="docutils literal notranslate"><span class="pre">early_pg_dir</span></code> which
allows discovery of the system memory. Only the kernel text/data are mapped
at this point. When establishing this mapping, no allocation can be done
(since the system memory is not known yet), so <code class="docutils literal notranslate"><span class="pre">early_pg_dir</span></code> page table is
statically allocated (using only one table for each level).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">setup_vm_final()</span></code> creates the final kernel mapping in <code class="docutils literal notranslate"><span class="pre">swapper_pg_dir</span></code>
and takes advantage of the discovered system memory to create the linear
mapping. When establishing this mapping, the kernel can allocate memory but
cannot access it directly (since the direct mapping is not present yet), so
it uses temporary mappings in the fixmap region to be able to access the
newly allocated page table levels.</p></li>
</ol>
<p>For <code class="docutils literal notranslate"><span class="pre">virt_to_phys()</span></code> and <code class="docutils literal notranslate"><span class="pre">phys_to_virt()</span></code> to be able to correctly convert
direct mapping addresses to physical addresses, they need to know the start of
the DRAM. This happens after step 1, right before step 2 installs the direct
mapping (see <code class="docutils literal notranslate"><span class="pre">setup_bootmem()</span></code> function in arch/riscv/mm/init.c). Any usage of
those macros before the final virtual mapping is installed must be carefully
examined.</p>
</section>
<section id="devicetree-mapping-via-fixmap">
<h3>Devicetree mapping via fixmap<a class="headerlink" href="#devicetree-mapping-via-fixmap" title="Link to this heading">¶</a></h3>
<p>As the <code class="docutils literal notranslate"><span class="pre">reserved_mem</span></code> array is initialized with virtual addresses established
by <code class="docutils literal notranslate"><span class="pre">setup_vm()</span></code>, and used with the mapping established by
<code class="docutils literal notranslate"><span class="pre">setup_vm_final()</span></code>, the RISC-V kernel uses the fixmap region to map the
devicetree. This ensures that the devicetree remains accessible by both virtual
mappings.</p>
</section>
<section id="pre-mmu-execution">
<h3>Pre-MMU execution<a class="headerlink" href="#pre-mmu-execution" title="Link to this heading">¶</a></h3>
<p>A few pieces of code need to run before even the first virtual mapping is
established. These are the installation of the first virtual mapping itself,
patching of early alternatives and the early parsing of the kernel command line.
That code must be very carefully compiled as:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">-fno-pie</span></code>: This is needed for relocatable kernels which use <code class="docutils literal notranslate"><span class="pre">-fPIE</span></code>,
since otherwise, any access to a global symbol would go through the GOT which
is only relocated virtually.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">-mcmodel=medany</span></code>: Any access to a global symbol must be PC-relative to
avoid any relocations to happen before the MMU is setup.</p></li>
<li><p><em>all</em> instrumentation must also be disabled (that includes KASAN, ftrace and
others).</p></li>
</ul>
<p>As using a symbol from a different compilation unit requires this unit to be
compiled with those flags, we advise, as much as possible, not to use external
symbols.</p>
</section>
</section>
</section>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
©The kernel development community.
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 8.1.3</a>
& <a href="https://alabaster.readthedocs.io">Alabaster 0.7.16</a>
|
<a href="../../_sources/arch/riscv/boot.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>