add section on SoC boot process
This commit is contained in:
75
docs/Customization/Boot-Process.rst
Normal file
75
docs/Customization/Boot-Process.rst
Normal file
@@ -0,0 +1,75 @@
|
||||
Chipyard Boot Process
|
||||
=======================
|
||||
|
||||
This section will describe in detail the process by which a Chipyard-based
|
||||
SoC boots a Linux kernel and the changes you can make to customize this process.
|
||||
|
||||
BootROM and RISC-V Frontend Server
|
||||
----------------------------------
|
||||
|
||||
The first instructions to run when the SoC is powered on are those stored in
|
||||
the BootROM. The assembly for the BootROM code is located in
|
||||
`generators/testchipip/src/main/resources/testchipip/bootrom/bootrom.S <https://github.com/ucb-bar/testchipip/blob/master/src/main/resources/testchipip/bootrom/bootrom.S>`_.
|
||||
The Chisel generator encodes the assembled instructions into the BootROM
|
||||
hardware at elaboration time, so if you want to change the BootROM code, you
|
||||
will need to run ``make`` in the bootrom directory and then regenerate the
|
||||
verilog. If you don't want to overwrite the existing ``bootrom.S``, you can
|
||||
also point the generator to a different bootrom image by overriding the
|
||||
``BootROMParams`` key in the configuration.
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
class WithMyBootROM extends Config((site, here, up) => {
|
||||
case BootROMParams =>
|
||||
BootROMParams(contentFileName = "/path/to/your/bootrom.img")
|
||||
})
|
||||
|
||||
The default bootloader simply loops on a wait-for-interrupt (WFI) instruction
|
||||
as the RISC-V frontend-server (FESVR) loads the actual program.
|
||||
FESVR is a program that runs on the host CPU and can read/write arbitrary
|
||||
parts of the target system memory using the Tethered Serial Interface (TSI).
|
||||
|
||||
FESVR uses TSI to load a baremetal executable or second-stage bootloader into
|
||||
the SoC memory. In :ref:`Software RTL Simulation`, this will be the binary you
|
||||
pass to the simulator. Once it is finished loading the program, FESVR will
|
||||
write to the software interrupt register for CPU 0, which will bring CPU 0
|
||||
out of its WFI loop. Once it receives the interrupt, CPU 0 will write to
|
||||
the software interrupt registers for the other CPUs in the system and then
|
||||
jump to the beginning of DRAM to execute the first instruction of the loaded
|
||||
executable. The other CPUs will be woken up by the first CPU and also jump
|
||||
to the beginning of DRAM.
|
||||
|
||||
The executable loaded by FESVR should have memory locations designated
|
||||
as *tohost* and *fromhost*. FESVR uses these memory locations to communicate
|
||||
with the executable once it is running. The executable uses *tohost* to send
|
||||
commands to FESVR for things like printing to the console,
|
||||
proxying system calls, and shutting down the SoC. The *fromhost* register is
|
||||
used to send back responses for *tohost* commands and for sending console
|
||||
input.
|
||||
|
||||
The Berkeley Boot Loader and RISC-V Linux
|
||||
-----------------------------------------
|
||||
|
||||
For baremetal programs, the story ends here. The loaded executable will run in
|
||||
machine mode until it sends a command through the *tohost* register telling the
|
||||
FESVR to power off the SoC.
|
||||
|
||||
However, for booting the Linux Kernel, you will need to use a second-stage
|
||||
bootloader called the Berkeley Boot Loader, or BBL. This program reads the
|
||||
device tree encoded in the boot ROM and transforms it into a format compatible
|
||||
with the Linux kernel. It then sets up virtual memory and the interrupt
|
||||
controller, loads the kernel, which is embedded in the bootloader binary as a
|
||||
payload, and starts executing the kernel in supervisor mode. The bootloader is
|
||||
also responsible for servicing machine-mode traps from the kernel and
|
||||
proxying them over FESVR.
|
||||
|
||||
Once BBL jumps into supervisor mode, the Linux kernel takes over and begins
|
||||
its process. It eventually loads the ``init`` program and runs it in user
|
||||
mode, thus starting userspace execution.
|
||||
|
||||
The easiest way to build a BBL image that boots Linux is to use the FireMarshal
|
||||
tool that lives in the `firesim-software <https://github.com/firesim/firesim-software>`_
|
||||
repository. Directions on how to use FireMarshal can be found in the
|
||||
`FireSim documentation <https://docs.fires.im/en/latest/Advanced-Usage/FireMarshal/index.html>`_.
|
||||
Using FireMarshal, you can add custom kernel configurations and userspace software
|
||||
to your workload.
|
||||
@@ -16,3 +16,4 @@ Hit next to get started!
|
||||
Heterogeneous-SoCs
|
||||
Adding-An-Accelerator
|
||||
Memory-Hierarchy
|
||||
Boot-Process
|
||||
|
||||
Reference in New Issue
Block a user