Thu 25 November 2021

Porting GNOME OS to Microchip's PolarFire Icicle Kit

We've ported GNOME OS to the PolarFire Icicle-kit development board from Microchip.

The dev board features a PolarFire SoC FPGA with 4 usable Application SiFive cores, which run at 600 MHz.

The dev board does not feature any sort of graphical outputs, but it does feature a PCIe port for expansion, so time was spent at the start of the project to test different GPUs with the dev board. We were limited to testing older and low-end graphics cards because the dev board features a single 12v barrel input. Jury-rigging an ATX PSU capable of providing auxillary power to a graphics card to work with the dev board would have been cumbersome. Cards from AMD and NVIDIA were both tested, but ultimately the only card which would POST with the dev board was ATI's 1GB HD6450. This seems to be because the PolarFire Icicle-Kit's PCIe implementation offers the cards a 512MB address space and most GPUs expect a much bigger window.

Because the dev board does not have a BIOS capable of POSTing the graphics card, and because we want a console as early as possible in the boot process; we compiled the firmware for the graphics card directly into the BSP's kernel.

GNOME OS and Freedesktop-SDK

Next we turned our attention to GNOME OS. GNOME OS is based on Freedesktop-SDK and is built with BuildStream. Codethink added support for producing builds for riscv64 to Freedesktop-SDK. GNOME OS leverages that to support other RISC-V based dev boards. As such, it was very easy to create an SD card with the PolarFire BSP, and a RISC-V-based root file system for GNOME OS, and then smash them together to produce a proof-of-concept.

The proof-of-concept was mostly successful, in that it was able to boot to a console on serial, but indicated Graphical Hardware Acceleration was going to be an issue. GDM would start without issue (a little slowly but considering the Icicle's specification, entirely normal), but there would only be static on the screen. We used the KMSCube application to debug the issue because it is substantially less complicated than trying to debug the issue in gnome-shell. We also tested using Weston in Freedesktop-SDK, and we tested Weston and KMSCube in the PolarFire buildroot BSP by enabling the relevent options. In all cases, we found software rendering using the softpipe driver was successful, but very slow, and hardware acceleration using the r600 driver resulted in static. Incidentally, at this time, buildroot will not build the r600 driver for anything but x86 targets, so only software rendering was tested under buildroot. We also tested the graphics card under other systems and confirmed that it worked properly. Ultimately we concluded that hardware acceleration was a lost cause on this board. We would proceed with software rendering using the softpipe driver.

A viable path forward plotted; it was then necessary to port over relevent bits of the BSPs into the GNOME OS project. It was simply a matter of creating a set of elements which would produce an SD card image as outlined by the polarfire BSP, while combinding the GNOME OS root file system with our adjustments to use softpipe, along with our special firmware-laden kernel.

Build it yourself

Our port of GNOME OS to the RISC-V board uses GNOME's gnome-build-meta repository, used by their release time to build the entire GNOME software stack.

It is a BuildStream project which uses the Freedesktop-SDK Linux software stack platform definitions as a base.

Environment setup

The first step is to ensure you have BuildStream installed. We used BuildStream version 1.6.1 because that is packaged on the Debian system we used.

BuildStream does not cross-compile, it does native compilation. In order to build for RISC-V on our x86-64 build machine, BuildStream uses QEMU to run RISC-V binaries under emulation.

To get this working we had to install QEMU from source because the version in Debian 10 was too old.

./configure --static --disable-system --target-list=riscv64-linux-user
make
sudo cp build/qemu-riscv64 /usr/bin/qemu-riscv64-static

After that we had to prod binfmt to use this to run RISC-V binaries.

# unregister existing
echo "-1" | sudo tee -a /proc/sys/fs/binfmt_misc/qemu-riscv64 

#register with F flag
echo ":qemu-riscv64:M:0:\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-riscv64-static:F" | sudo tee -a /proc/sys/fs/binfmt_misc/register 

Build

First you need the source. Our work is on the robjh/icicle-kit-master. branch:

git clone https://gitlab.gnome.org/scott.clarke/gnome-build-meta.git
cd gnome-build-meta
git checkout robjh/icicle-kit-master

Now that you have the source, you can start the build:

bst -o arch riscv64 build --track-all boards/icicle-kit/image.bst

This will take a long time. BuildStream first bootstrap builds GCC to ensure that the final artifact is completely reproducible from known sources.

Additionally running the RISC-V-native GCC under emulation means it will take a long time. In particular LLVM and Rust are slow to build. Overall our build took well over 40 hours.

Once the build completes, you will be able to check it out with:

bst -o arch riscv64 checkout boards/icicle-kit/image.bst here

The exact command might be different with another version of BuildStream. The output is an SD card image:

ls here
sdcard.img

Deploying onto a board

Insert an SD card and find its device path.

export SDCARD=/dev/mmcblk0
sudo dd if=checkout/sdcard.img of=${SDCARD} bs=4k

Now insert the card into the board and turn it on.

Links

Related content

Other Articles

Get in touch to find out how Codethink can help you

sales@codethink.co.uk +44 161 660 9930