Linux Kernel Module Initialization of FPGA Soft-Processor Instruction Memory
During the development of a hardware implementation of the Homa transport protocol I experimented with using a RISC-V soft-processor for running small user defined codelets. The Linux Kernel was responsible for initializing the PicoRV soft-processors instruction memory. This document details how to take a cross compiled RISC-V ELF file, dump it to a binary blob, convert it to an x64-64 elf, and compile it into the kernel module.
Cross-compiling for the PicoRV was accomplished with the following command, which generated a RISC-V ELF file called firmware.
riscv32-unknown-elf-gcc -ffreestanding -nostartfiles -nostdlib -Qn -static -Wl,--strip-debug,-Bstatic,-T,picorv.ld homa.c reset.s -o firmware
The PicoRV expected a raw binary blob of instructions, not an ELF, so can we convert firmware to a blob.
riscv32-unknown-elf-objcopy -O binary firmware
The PicoRV's instruction memory space was mapped to a DMA region within the kernel module and needed to be initialized with firmware, now a blob of RISC-V instructions. The faculties for reading files from within the kernel module are limited. This made it challenging to read the contents of firmware and write it to the PicoRV's memory. Instead, I opted to copy the binary blob of RISC-V instructions into an x86 ELF file, which I would then link into the kernel module at compilation.
Copying the firmware blob to an x86 ELF can be accomplished with the following command.
objcopy -I binary -O elf64-x86-64 -B i386:x86-64 firmware firmware.o
The object file can be included in the kernel module build procedure.
obj-m := homanicmodule.o homanicmodule-y += homanic.o firmware.o PWD := $(CURDIR) CFLAGS_homanic.o := -mavx2 all: cp ../firmware/firmware.o . make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean rm -rf app
Then the raw binary blob can be accessed from within the kernel module as a char buffer.
extern char _binary_firmware_start[]; extern char _binary_firmware_end[];
RISC-V instructions can be read from this char buffer and written to the DMA buffer associated with the PicoRV's memory space.