From Fedora Project Wiki
(Mention Fedora 29 for libvirt and how to disable autoconsole)
m (Real hardware instructions have been dropped for now)
 
(43 intermediate revisions by 7 users not shown)
Line 1: Line 1:
= Download the latest disk image =
This page describes the steps necessary to get Fedora for RISC-V running on emulated hardware.


Go [http://fedora-riscv.tranquillity.se/koji/tasks?state=closed&view=flat&method=createAppliance&order=-id to this link for the nightly builds] and select the most recent (top) build.  Look for the <code>-sda.raw.xz</code> file and download it.  It will usually be quite large, around 200-300 MB.
= Quickstart =


Uncompress it:
This section assumes that you have already set up libvirt/QEMU on your machine and you're familiar with them, so it only highlights the details that are specific to RISC-V. It also assumes that you're running Fedora 40 as the host.
 
First of all, you need to download a disk image from https://dl.fedoraproject.org/pub/alt/risc-v/disk_images/Fedora-40/
 
As of this writing, the most recent image is <code>Fedora-Minimal-40-20240502.n.0-sda.raw.xz</code> so I will be using that throughout the section. If you're using a different image, you will need to adjust things accordingly.
 
Once you've downloaded the image, start by uncompressing it:


<pre>
<pre>
$ unxz Fedora-Developer-Rawhide-xxxx.n.0-sda.raw.xz
$ unxz Fedora-Minimal-40-20240502.n.0-sda.raw.xz
</pre>
</pre>


== Root password ==
You need to figure out the root filesystem's UUID so that you can later pass this information to the kernel. The <code>virt-filesystems</code> utility, part of the <code>guestfs-tools</code> package, takes care of that:


<code>riscv</code>
<pre>
$ virt-filesystems \
    -a Fedora-Minimal-40-20240502.n.0-sda.raw \
    --long \
    --uuid \
  | grep ^btrfsvol: \
  | awk '{print $7}' \
  | sort -u
ae525e47-51d5-4c98-8442-351d530612c3
</pre>


= Boot under TinyEMU (RISCVEMU) =
Additionally, you need to extract the kernel and initrd from the disk image. The <code>virt-get-kernel</code> tool automates this step:


RISCVEMU recently (2018-09-23) was renamed to TinyEMU (https://bellard.org/tinyemu/).
<pre>
$ virt-get-kernel \
    -a Fedora-Minimal-40-20240502.n.0-sda.raw
download: /boot/vmlinuz-6.8.7-300.4.riscv64.fc40.riscv64 -> ./vmlinuz-6.8.7-300.4.riscv64.fc40.riscv64
download: /boot/initramfs-6.8.7-300.4.riscv64.fc40.riscv64.img -> ./initramfs-6.8.7-300.4.riscv64.fc40.riscv64.img
</pre>


TinyEMU allow booting Fedora disk images in TUI and GUI modes. You can experiment using JSLinux (no need to download/compile/etc) here: https://bellard.org/jslinux/
Now move all the files to a directory that libvirt has access to:


Below are instructions how to boot Fedora into X11/Fluxbox GUI mode.
<pre>
$ sudo mv
    Fedora-Minimal-40-20240502.n.0-sda.raw \
    vmlinuz-6.8.7-300.4.riscv64.fc40.riscv64 \
    initramfs-6.8.7-300.4.riscv64.fc40.riscv64.img \
    /var/lib/libvirt/images/
</pre>


'''Step 1'''. Compile TinyEMU:
At this point, everything is ready and you can create the libvirt VM:


<pre>
<pre>
wget https://bellard.org/tinyemu/tinyemu-2018-09-23.tar.gz
$ virt-install \
tar xvf tinyemu-2018-09-23.tar.gz
    --import \
cd tinyemu-2018-09-23
    --name fedora-riscv \
make
    --osinfo fedora40 \
    --arch riscv64 \
    --vcpus 4 \
    --ram 4096 \
    --boot uefi,kernel=/var/lib/libvirt/images/vmlinuz-6.8.7-300.4.riscv64.fc40.riscv64,initrd=/var/lib/libvirt/images/initramfs-6.8.7-300.4.riscv64.fc40.riscv64.img,cmdline='root=UUID=ae525e47-51d5-4c98-8442-351d530612c3 ro rootflags=subvol=root rhgb LANG=en_US.UTF-8 console=ttyS0 earlycon=sbi' \
    --disk path=/var/lib/libvirt/images/Fedora-Minimal-40-20240502.n.0-sda.raw \
    --network default \
    --tpm none \
    --graphics none
</pre>
</pre>


'''Step 2'''. Setup for booting Fedora:
Note how the UUID discovered earlier is included in the kernel command line. Quoting is also very important to get right.
 
Disabling the TPM with <code>--tpm none</code> is only necessary as a temporary measure due to issues currently affecting swtpm in Fedora 40. If you want to, you can try omitting that option and see whether it works.
 
You should see a bunch of output coming from edk2 (the UEFI implementation we're using), followed by the usual kernel boot messages and, eventually, a login prompt. Please be patient, as the use of emulation makes everything significantly slower. Additionally, a SELinux relabel followed by a reboot will be performed as part of the import process, which slows things down further. Subsequent boots will be a lot faster.
 
To shut down the VM, run <code>poweroff</code> inside the guest OS. To boot it up again, use
 
<pre>
<pre>
mkdir fedora
$ virsh start fedora-riscv --console
cd fedora
</pre>
cp ../temu .
 


# Download pre-built BBL with embedded kernel
= UKI images =
wget https://bellard.org/jslinux/bbl64-4.15.bin


# Create configuration file for TinyEMU
These can be found in the same location but follow a different naming convention. As of this writing, the most recent image is <code>Fedora.riscv64-40-20240429.n.0.qcow2</code>.
cat <<EOF > root-riscv64.cfg
/* VM configuration file */
{
    version: 1,
    machine: "riscv64",
    memory_size: 1400,
    bios: "bbl64-4.15.bin",
    cmdline: "loglevel=3 console=tty0 root=/dev/vda1 rw TZ=${TZ}",
    drive0: { file: "Fedora-Developer-Rawhide-xxxx.n.0-sda.raw" },
    eth0: { driver: "user" },
    display0: {
        device: "simplefb",
        width: 1920,
        height: 1080,
    },
    input_device: "virtio",
}
EOF


# Download disk image and unpack in the same directory
The steps are similar to those described above, except that instead of dealing with kernel and initrd separately you need to extract a single file:
</pre>


'''Step 3'''. Boot it.
<pre>
<pre>
./temu -rw root-riscv64.cfg
$ virt-copy-out \
    -a Fedora.riscv64-40-20240429.n.0.qcow2 \
    /boot/efi/EFI/Linux/6.8.7-300.4.riscv64.fc40.riscv64.efi \
    .
</pre>
</pre>


We need to use <code>-rw</code> if we want our changes to persist in disk image. Otherwise disk image will be loaded as read-only and all changes will not persist after reboot.
The <code>virt-install</code> command line is slightly different too, in particular the <code>--boot</code> option becomes:


Once the system is booted login as <code>root</code> with <code>riscv</code> as password. Finally start X11 with Fluxbox: <code>startx /usr/bin/startfluxbox</code>. To gratefully shutdown just type <code>poweroff</code> into console.
<pre>
--boot uefi,kernel=/var/lib/libvirt/images/6.8.7-300.4.riscv64.fc40.riscv64.efi,cmdline='root=UUID=57cbf0ca-8b99-45ae-ae9d-3715598f11c4 ro rootflags=subvol=root rhgb LANG=en_US.UTF-8 console=ttyS0 earlycon=sbi'
</pre>


The disk image also incl. awesome and i3 for testing. Dillo is available as a basic web browser (no javascript support) and pcmanfm as file manager.
These changes are enough to get the image to boot, but there are no passwords set up so you won't be able to log in. In order to address that, it's necessary to create a configuration file for <code>cloud-init</code>, for example with the following contents:


= Boot under qemu =
<pre>
#cloud-config


You will need a very recent version of qemu.  If in doubt, compile from upstream qemu sources.
password: fedora_rocks!
chpasswd:
  expire: false
</pre>


Get [https://fedorapeople.org/groups/risc-v/disk-images/bbl bbl from here] or [https://github.com/rwmjones/fedora-riscv-kernel compile it from source].
Save this as `user-data.yml`, then add the following options to your <code>virt-install</code> command line:


<pre>
<pre>
qemu-system-riscv64 \
--controller scsi,model=virtio-scsi \
    -nographic \
--cloud-init user-data=user-data.yml
    -machine virt \
    -smp 4 \
    -m 2G \
    -kernel bbl \
    -object rng-random,filename=/dev/urandom,id=rng0 \
    -device virtio-rng-device,rng=rng0 \
    -append "console=ttyS0 ro root=/dev/vda1" \
    -device virtio-blk-device,drive=hd0 \
    -drive file=Fedora-Developer-Rawhide-xxxx.n.0-sda.raw,format=raw,id=hd0 \
    -device virtio-net-device,netdev=usernet \
    -netdev user,id=usernet,hostfwd=tcp::10000-:22
</pre>
</pre>


= Boot with libvirt =
The configuration data should be picked up during boot, setting the default user's password as requested and allowing you to log in.


Needs <b>libvirt &ge; 4.7.0</b> which is the first version with upstream RISC-V support. This is available in Fedora 29. You should be able to boot the disk image using a command similar to this:
 
= Host setup =
 
The steps outlined above assume that your machine is already set up for running RISC-V VMs. If that's not the case, read on.
 
At the very least, the following package will need to be installed:


<pre>
<pre>
# virt-install \
$ sudo dnf install \
     --name fedora-riscv \
     libvirt-daemon-driver-qemu \
     --arch riscv64 \
     libvirt-daemon-driver-network \
    --machine virt \
     libvirt-daemon-config-network \
     --vcpus 4 \
     libvirt-client \
    --memory 2048 \
     virt-install \
     --import \
     qemu-system-riscv-core \
    --disk path=/var/lib/libvirt/images/Fedora-Developer-Rawhide-xxxx.n.0-sda.raw,bus=virtio \
     edk2-riscv64
     --boot kernel=/var/lib/libvirt/images/bbl,kernel_args="console=ttyS0 ro root=/dev/vda1" \
     --network network=default,model=virtio \
    --rng device=/dev/urandom,model=virtio \
     --graphics none
</pre>
</pre>


Note that will automatically boot you into the console. If you don't want that add <code>--noautoconsole</code> option. You can later use <code>virsh</code> tool to manage your VM and get to console.
This will result in a fairly minimal install, suitable for running headless VMs. If you'd rather have a fully-featured install, add <code>libvirt-daemon-qemu</code> and <code>libvirt-daemon-config-nwfilter</code> to the list. Be warned though: doing so will result in significantly more packages being dragged in, some of which you might not care about (e.g. support for several additional architectures).


= Install on the HiFive Unleashed SD card =
In order to grant your user access to libvirt and allow it to manage VMs, it needs to be made a member of the corresponding group:


These are instructions for the [https://www.sifive.com/products/hifive-unleashed/ HiFive Unleashed board].
<pre>
$ sudo usermod -a -G libvirt $(whoami)
</pre>


The disk image (above) is partitioned, but usually we need an unpartitioned ("naked") filesystem.  There are several ways to get this, but the easiest is:
Finally, the default libvirt URI needs to be configured:


<pre>
<pre>
$ guestfish -a Fedora-Developer-Rawhide-xxxx.n.0-sda.raw \
$ mkdir -p ~/.config/libvirt && \
    run : download /dev/sda1 Fedora-Developer-Rawhide-xxxx.n.0-sda1.raw
  echo 'uri_default = "qemu:///system"' >~/.config/libvirt/libvirt.conf
</pre>
</pre>


This creates a naked ext4 filesystem called <code>*-sda1.raw</code>.  The naked ext4 filesystem can be copied over the second partition of the SD card.
Now reboot the host. This is necessary because the changes to group membership won't be effective until the next login, and because the libvirt services are not automatically started during package installation.
 
After rebooting and logging back in, <code>virsh</code> should work and the default network should be up:


You can also build a custom bbl+kernel+initramfs to boot directly into the SD card using [https://github.com/rwmjones/fedora-riscv-kernel these sources].
<pre>
$ virsh uri
qemu:///system


= Install on the HiFive Unleashed using NBD server =
$ virsh net-list
Name      State    Autostart  Persistent
--------------------------------------------
default  active  yes        yes
</pre>


Look at https://github.com/rwmjones/fedora-riscv-kernel in the <code>sifive_u540</code> branch.  This is quite complex to set up so it's best to ask on the <code>#fedora-riscv</code> IRC channel.
All done! You can now start creating RISC-V VMs.

Latest revision as of 13:30, 10 June 2024

This page describes the steps necessary to get Fedora for RISC-V running on emulated hardware.

Quickstart

This section assumes that you have already set up libvirt/QEMU on your machine and you're familiar with them, so it only highlights the details that are specific to RISC-V. It also assumes that you're running Fedora 40 as the host.

First of all, you need to download a disk image from https://dl.fedoraproject.org/pub/alt/risc-v/disk_images/Fedora-40/

As of this writing, the most recent image is Fedora-Minimal-40-20240502.n.0-sda.raw.xz so I will be using that throughout the section. If you're using a different image, you will need to adjust things accordingly.

Once you've downloaded the image, start by uncompressing it:

$ unxz Fedora-Minimal-40-20240502.n.0-sda.raw.xz

You need to figure out the root filesystem's UUID so that you can later pass this information to the kernel. The virt-filesystems utility, part of the guestfs-tools package, takes care of that:

$ virt-filesystems \
    -a Fedora-Minimal-40-20240502.n.0-sda.raw \
    --long \
    --uuid \
  | grep ^btrfsvol: \
  | awk '{print $7}' \
  | sort -u
ae525e47-51d5-4c98-8442-351d530612c3

Additionally, you need to extract the kernel and initrd from the disk image. The virt-get-kernel tool automates this step:

$ virt-get-kernel \
    -a Fedora-Minimal-40-20240502.n.0-sda.raw
download: /boot/vmlinuz-6.8.7-300.4.riscv64.fc40.riscv64 -> ./vmlinuz-6.8.7-300.4.riscv64.fc40.riscv64
download: /boot/initramfs-6.8.7-300.4.riscv64.fc40.riscv64.img -> ./initramfs-6.8.7-300.4.riscv64.fc40.riscv64.img

Now move all the files to a directory that libvirt has access to:

$ sudo mv
    Fedora-Minimal-40-20240502.n.0-sda.raw \
    vmlinuz-6.8.7-300.4.riscv64.fc40.riscv64 \
    initramfs-6.8.7-300.4.riscv64.fc40.riscv64.img \
    /var/lib/libvirt/images/

At this point, everything is ready and you can create the libvirt VM:

$ virt-install \
    --import \
    --name fedora-riscv \
    --osinfo fedora40 \
    --arch riscv64 \
    --vcpus 4 \
    --ram 4096 \
    --boot uefi,kernel=/var/lib/libvirt/images/vmlinuz-6.8.7-300.4.riscv64.fc40.riscv64,initrd=/var/lib/libvirt/images/initramfs-6.8.7-300.4.riscv64.fc40.riscv64.img,cmdline='root=UUID=ae525e47-51d5-4c98-8442-351d530612c3 ro rootflags=subvol=root rhgb LANG=en_US.UTF-8 console=ttyS0 earlycon=sbi' \
    --disk path=/var/lib/libvirt/images/Fedora-Minimal-40-20240502.n.0-sda.raw \
    --network default \
    --tpm none \
    --graphics none

Note how the UUID discovered earlier is included in the kernel command line. Quoting is also very important to get right.

Disabling the TPM with --tpm none is only necessary as a temporary measure due to issues currently affecting swtpm in Fedora 40. If you want to, you can try omitting that option and see whether it works.

You should see a bunch of output coming from edk2 (the UEFI implementation we're using), followed by the usual kernel boot messages and, eventually, a login prompt. Please be patient, as the use of emulation makes everything significantly slower. Additionally, a SELinux relabel followed by a reboot will be performed as part of the import process, which slows things down further. Subsequent boots will be a lot faster.

To shut down the VM, run poweroff inside the guest OS. To boot it up again, use

$ virsh start fedora-riscv --console


UKI images

These can be found in the same location but follow a different naming convention. As of this writing, the most recent image is Fedora.riscv64-40-20240429.n.0.qcow2.

The steps are similar to those described above, except that instead of dealing with kernel and initrd separately you need to extract a single file:

$ virt-copy-out \
    -a Fedora.riscv64-40-20240429.n.0.qcow2 \
    /boot/efi/EFI/Linux/6.8.7-300.4.riscv64.fc40.riscv64.efi \
    .

The virt-install command line is slightly different too, in particular the --boot option becomes:

--boot uefi,kernel=/var/lib/libvirt/images/6.8.7-300.4.riscv64.fc40.riscv64.efi,cmdline='root=UUID=57cbf0ca-8b99-45ae-ae9d-3715598f11c4 ro rootflags=subvol=root rhgb LANG=en_US.UTF-8 console=ttyS0 earlycon=sbi'

These changes are enough to get the image to boot, but there are no passwords set up so you won't be able to log in. In order to address that, it's necessary to create a configuration file for cloud-init, for example with the following contents:

#cloud-config

password: fedora_rocks!
chpasswd:
  expire: false

Save this as user-data.yml, then add the following options to your virt-install command line:

--controller scsi,model=virtio-scsi \
--cloud-init user-data=user-data.yml

The configuration data should be picked up during boot, setting the default user's password as requested and allowing you to log in.


Host setup

The steps outlined above assume that your machine is already set up for running RISC-V VMs. If that's not the case, read on.

At the very least, the following package will need to be installed:

$ sudo dnf install \
    libvirt-daemon-driver-qemu \
    libvirt-daemon-driver-network \
    libvirt-daemon-config-network \
    libvirt-client \
    virt-install \
    qemu-system-riscv-core \
    edk2-riscv64

This will result in a fairly minimal install, suitable for running headless VMs. If you'd rather have a fully-featured install, add libvirt-daemon-qemu and libvirt-daemon-config-nwfilter to the list. Be warned though: doing so will result in significantly more packages being dragged in, some of which you might not care about (e.g. support for several additional architectures).

In order to grant your user access to libvirt and allow it to manage VMs, it needs to be made a member of the corresponding group:

$ sudo usermod -a -G libvirt $(whoami)

Finally, the default libvirt URI needs to be configured:

$ mkdir -p ~/.config/libvirt && \
  echo 'uri_default = "qemu:///system"' >~/.config/libvirt/libvirt.conf

Now reboot the host. This is necessary because the changes to group membership won't be effective until the next login, and because the libvirt services are not automatically started during package installation.

After rebooting and logging back in, virsh should work and the default network should be up:

$ virsh uri
qemu:///system

$ virsh net-list
 Name      State    Autostart   Persistent
--------------------------------------------
 default   active   yes         yes

All done! You can now start creating RISC-V VMs.