resources: Add resources to run riscv full system simulations
Change-Id: Ibbce553b8868ea3a12da04e993007ee4bd922488
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5-resources/+/42241
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
Tested-by: Bobby R. Bruce <bbruce@ucdavis.edu>
diff --git a/README.md b/README.md
index b58d692..0c7d6e3 100644
--- a/README.md
+++ b/README.md
@@ -402,7 +402,7 @@
processor included in the GCN_X86 build of gem5.
The example command extracts the kernel's completion signal from the domain
-of the command processor and the GPU's dispatcher. Initially this was a
+of the command processor and the GPU's dispatcher. Initially this was a
workaround for the hipDeviceSynchronize bug, now fixed. The method of
waiting on a signal can be applied to other agent packet commands though.
@@ -742,6 +742,17 @@
The instructions to build the boot-tests disk image (`boot-exit`), the Linux binaries, and how to use gem5 run scripts to run boot-tests are available in this [README](src/boot-tests/README.md) file.
+# Resource: RISCV Full System Test
+
+This resource refers to a simple setup for a riscv based full system simulation of Linux kernel.
+
+Main components include:
+- a disk image
+- a riscv boot loader with linux kernel as payload and a device tree compiled in
+- gem5 run/config scripts
+
+The instructions to build a riscv disk image, a riscv boot loader (`berkeley bootloader (bbl)`) and how to use gem5 scripts to run riscv Linux full system simulations are available in this [README](src/riscv-fs/README.md) file.
+
# Resource: Insttest
The Insttests test SPARC instructions.
diff --git a/src/riscv-fs/README.md b/src/riscv-fs/README.md
new file mode 100644
index 0000000..507e45a
--- /dev/null
+++ b/src/riscv-fs/README.md
@@ -0,0 +1,254 @@
+# RISCV Full System
+
+This document provides instructions to create a riscv disk image, a riscv boot loader (`berkeley bootloader (bbl)`) and also points to the associated gem5 scripts to run riscv Linux full system simulations.
+The boot loader `bbl` is compiled with a Linux kernel and a device tree as well.
+
+The used disk image is based on [busybox](https://busybox.net/) and [UCanLinux](https://github.com/UCanLinux/). It is built using the instructions, mostly from [here](https://github.com/UCanLinux/riscv64-sample).
+
+All components are cross compiled on an x86 host using a riscv tool chain.
+
+We assume the following directory structure while following the instructions in this README file:
+
+```
+riscv-fs/
+ |___ gem5/ # gem5 source code (to be cloned here)
+ |
+ |___ riscv-disk # built disk image will go here
+ |
+ |___ device.dts # device tree file to use with bbl
+ |
+ |___ riscv-gnu-toolchain # riscv tool chain for cross compilation
+ |
+ |___ riscv64-sample # UCanLinux source
+ | |__linux # linux source
+ | |__busybox # busybox source
+ | |__riscv-pk # riscv proxy kernel source (bbl)
+ | |__RootFS # root file system for disk image
+ |
+ |
+ |___ configs-riscv-fs
+ | |___ system # gem5 system config files
+ | |___ run_riscv.py # gem5 run script
+ |
+ |
+ |___ README.md # This README file
+```
+
+## RISCV Toolchain
+
+We use `RISC-V GNU Compiler Toolchain`. To build the toolchain, follow the following instructions, assuming you are in the `riscv-fs` directory.
+
+```sh
+# install required libraries
+sudo apt-get install -y autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev
+
+# clone riscv gnu toolchain source
+git clone https://github.com/riscv/riscv-gnu-toolchain
+cd riscv-gnu-toolchain
+
+# change the prefix to your directory
+# of choice for installation of the
+# toolchain
+./configure --prefix=/opt/riscv
+
+# build the toolchain
+make linux -j$(nproc)
+```
+
+Update the `PATH` environment variable so that the following instructions can figure out where to find the riscv toolchain.
+
+```sh
+export PATH=$PATH:/opt/riscv/bin/
+```
+
+***Note:** The above step is necessary and might cause errors while cross compiling different components for riscv if other methods are used to point to the toolchain.
+
+## UCanLinux Source
+
+Clone the `UCanLinux source.`
+
+```sh
+# going back to base riscv-fs directory
+cd ../
+
+git clone https://github.com/UCanLinux/riscv64-sample
+```
+
+This source contains already built bootloader and disk images as well. Though the given disk image might be usable with gem5, the `bbl` (bootloader image) will not work with gem5 and we need to compile `bbl` with an input device tree (`.dts`) file separately. The following sections provide instructions to build both `bbl` and disk images.
+
+## Linux Kernel
+
+Clone the latest LTS Linux kernel (v5.10):
+
+```sh
+cd riscv64-sample/
+git clone --depth 1 --branch v5.10 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
+```
+
+To configure and compile the kernel:
+
+```sh
+cd linux
+
+# copy the kernel config from the riscv64-sample
+# directory (cloned previously)
+
+cp ../kernel.config .config
+
+# configure the kernel and build it
+make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- menuconfig
+make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- all -j$(nproc)
+```
+
+This should generate a `vmlinux` image in the `linux` directory.
+
+## Bootloader (bbl)
+
+To build the bootloader, clone the RISCV proxy kernel (`pk`) source, which is an application execution environment and contains the bbl source as well.
+
+```sh
+# going back to base riscv64-sample directory
+cd ../
+git clone https://github.com/riscv/riscv-pk.git
+
+cd riscv-pk
+
+mkdir build
+cd build
+
+apt-get install device-tree-compiler
+
+# copy the device tree file from riscv-fs
+cp ../../../device.dts .
+
+../configure --host=riscv64-unknown-linux-gnu --with-payload=../../linux/vmlinux --prefix=/opt/riscv/ --with-dts=device.dts
+make -j$(nproc)
+
+chmod 755 bbl
+
+# optional: strip the bbl binary
+riscv64-unknown-linux-gnu-strip bbl
+```
+
+This will produce a `bbl` bootloader binary with linux kernel in `riscv-pk/build` directory.
+
+## Busy Box
+
+Clone and compile the busybox:
+
+```sh
+# going back to riscv64-sample directory
+cd ../..
+git clone git://busybox.net/busybox.git
+cd busybox
+git checkout 1_30_stable # checkout the latest stable branch
+make menuconfig
+cp ../sample/busybox.config .config # optional
+make menuconfig
+make CROSS_COMPILE=riscv64-unknown-linux-gnu- all -j$(nproc)
+make CROSS_COMPILE=riscv64-unknown-linux-gnu- install
+```
+
+## Root File System for Disk Image
+
+Next, we will be setting up a root file system:
+
+```sh
+# going back to riscv64-sample directory
+cd ../..
+
+mkdir RootFS
+cd RootFS
+cp -a ../skeleton/* .
+
+# copy linux tools/binaries from busbybox (created above)
+cp -a ../busybox/_install/* .
+
+# install modules from linux kernel compiled above
+cd ../linux/
+make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- INSTALL_MOD_PATH=../RootFS modules_install
+
+# install libraries from the toolchain built above
+cd ../RootFS
+cp -a /opt/riscv/sysroot/lib .
+
+# create empty directories
+mkdir dev home mnt proc sys tmp var
+cd etc/network
+mkdir if-down.d if-post-down.d if-pre-up.d if-up.d
+
+# build m5 util for riscv and move
+# it to the root file system as well
+cd ../../../
+cd gem5/util/m5
+scons -C util/m5 build/riscv/out/m5
+cp build/riscv/out/m5 ../../../RootFS/sbin/
+```
+
+## Disk Image
+
+Create a disk of 512MB size.
+
+```sh
+cd ../../../
+dd if=/dev/zero of=riscv_disk bs=1M count=512
+```
+
+Making and mounting a root file system on the disk:
+
+```sh
+mkfs.ext2 -L riscv-rootfs riscv_disk
+
+sudo mkdir /mnt/rootfs
+sudo mount riscv_disk /mnt/rootfs
+
+sudo cp -a RootFS/* /mnt/rootfs
+
+sudo chown -R -h root:root /mnt/rootfs/
+df /mnt/rootfs
+# make sure you are in riscv64-sample dir
+cd ../riscv64-sample
+sudo umount /mnt/rootfs
+```
+
+The disk image `riscv_disk` is ready to use.
+
+**Note:** If you need to resize the disk image once it is created, you can do the following:
+
+```sh
+e2fsck -f riscv_disk
+resize2fs ./riscv_disk 512M
+```
+
+Also, if it is required to change the contents of the disk image, it can be mounted as:
+
+```sh
+mount -o loop riscv_disk [some mount directory]
+```
+
+## gem5 Run Scripts
+
+gem5 scripts which can configure a riscv full system and run simulation are available in configs-riscv-fs/.
+The main script `run_riscv.py` expects following arguments:
+
+**bbl:** path to the bbl (berkeley bootloader) binary with kernel payload.
+
+**disk:** path to the disk image to use.
+
+**cpu_type:** cpu model (`atomic`, `simple`).
+
+**num_cpus:** number of cpu cores.
+
+An example use of this script is the following:
+
+```sh
+[gem5 binary] -re configs/run_exit.py [path to bbl] [path to the disk image] atomic 4
+```
+
+To interact with the simulated system's console:
+
+```sh
+telnet localhost 3457 (this port number comes from `simerr` file)
+```
+
+The default linux system based on this README, has both `login` and `password` set as `root`.
diff --git a/src/riscv-fs/configs-riscv-fs/run_riscv.py b/src/riscv-fs/configs-riscv-fs/run_riscv.py
new file mode 100755
index 0000000..1ca8665
--- /dev/null
+++ b/src/riscv-fs/configs-riscv-fs/run_riscv.py
@@ -0,0 +1,84 @@
+# Copyright (c) 2021 The Regents of the University of California.
+# All Rights Reserved
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""
+This script is supposed to run full system simulation for RISCV targets.
+It has been tested with classic memory system and Atomic
+and TimingSimpleCPU so far.
+"""
+
+import time
+import argparse
+
+import m5
+import m5.ticks
+from m5.objects import *
+
+from system import *
+
+def parse_options():
+ parser = argparse.ArgumentParser(description='Runs Linux fs test with'
+ 'RISCV.')
+ parser.add_argument("bbl", help='Path to the bbl (berkeley bootloader)'
+ 'binary with kernel payload')
+ parser.add_argument("disk", help="Path to the disk image to boot")
+ parser.add_argument("cpu_type", help="The type of CPU in the system")
+ parser.add_argument("num_cpus", type=int, help="Number of CPU cores")
+
+ return parser.parse_args()
+
+if __name__ == "__m5_main__":
+
+ args = parse_options()
+
+ # create the system we are going to simulate
+
+ system = RiscvSystem(args.bbl, args.disk, args.cpu_type, args.num_cpus)
+
+ # set up the root SimObject and start the simulation
+ root = Root(full_system = True, system = system)
+
+ # Uncomment for long-running jobs
+ # and when the user does not
+ # need to interact with the
+ # simulated sytem
+
+ # m5.disableAllListeners()
+
+ # instantiate all of the objects we've created above
+ m5.instantiate()
+
+ globalStart = time.time()
+
+ print("Running the simulation")
+ exit_event = m5.simulate()
+
+ if exit_event.getCause() == "m5_exit instruction encountered":
+ print("The user has terminated the simulation using m5")
+ exit(0)
+ else:
+ print("Simulation terminated without using m5")
+ exit(1)
diff --git a/src/riscv-fs/configs-riscv-fs/system/__init__.py b/src/riscv-fs/configs-riscv-fs/system/__init__.py
new file mode 100755
index 0000000..e15a8e8
--- /dev/null
+++ b/src/riscv-fs/configs-riscv-fs/system/__init__.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2021 The Regents of the University of California.
+# All Rights Reserved
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from .system import RiscvSystem
+
diff --git a/src/riscv-fs/configs-riscv-fs/system/system.py b/src/riscv-fs/configs-riscv-fs/system/system.py
new file mode 100755
index 0000000..5032664
--- /dev/null
+++ b/src/riscv-fs/configs-riscv-fs/system/system.py
@@ -0,0 +1,228 @@
+# Copyright (c) 2021 The Regents of the University of California.
+# All Rights Reserved
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import m5
+from m5.objects import *
+from m5.util import convert
+
+'''
+This class creates a bare bones RISCV full system.
+
+The targeted system is based on SiFive FU540-C000.
+Reference:
+[1] https://sifive.cdn.prismic.io/sifive/b5e7a29c-
+d3c2-44ea-85fb-acc1df282e21_FU540-C000-v1p3.pdf
+'''
+
+class RiscvSystem(System):
+
+ def __init__(self, bbl, disk, cpu_type, num_cpus):
+ super(RiscvSystem, self).__init__()
+
+ # Set up the clock domain and the voltage domain
+ self.clk_domain = SrcClockDomain()
+ self.clk_domain.clock = '3GHz'
+ self.clk_domain.voltage_domain = VoltageDomain()
+
+ # DDR memory range starts from base address 0x80000000
+ # based on [1]
+ self.mem_ranges = [AddrRange(start=0x80000000, size='1GB')]
+
+ # Create the main memory bus
+ # This connects to main memory
+ self.membus = SystemXBar(width = 64) # 64-byte width
+
+ # Set up the system port for functional access from the simulator
+ self.system_port = self.membus.cpu_side_ports
+
+ # Create the CPUs for our system.
+ self.createCPU(cpu_type, num_cpus)
+
+ # using RISCV bare metal as the base full system workload
+ self.workload = RiscvBareMetal()
+
+ # this is user passed berkeley boot loader binary
+ # currently the Linux kernel payload is compiled into this
+ # as well
+ self.workload.bootloader = bbl
+
+ # HiFive platform
+ # This is based on a HiFive RISCV board and has
+ # only a limited number of devices so far i.e.
+ # PLIC, CLINT, UART, VirtIOMMIO
+ self.platform = HiFive()
+
+ # Next, create and intialize devices
+ # currently supported for RISCV
+
+ # add a disk image
+ self.attachDisk(disk)
+
+ # set up core and platform
+ # level interrupt controllers
+ self.setupIntrCtrl()
+
+ # set up PMA checker
+ self.pmaChecker()
+
+ # attach off and on chip IO
+ self.attachIO(self.membus)
+
+ # Create the cache heirarchy for the system.
+ self.createCacheHierarchy()
+
+ # Create the memory controller
+ self.createMemoryControllerDDR3()
+
+ self.setupInterrupts()
+
+ def createCPU(self, cpu_type, num_cpus):
+ if cpu_type == "atomic":
+ self.cpu = [AtomicSimpleCPU(cpu_id = i)
+ for i in range(num_cpus)]
+ self.mem_mode = 'atomic'
+ elif cpu_type == "simple":
+ self.cpu = [TimingSimpleCPU(cpu_id = i)
+ for i in range(num_cpus)]
+ self.mem_mode = 'timing'
+ else:
+ m5.fatal("No CPU type {}".format(cpu_type))
+
+ for cpu in self.cpu:
+ cpu.createThreads()
+
+
+ def createCacheHierarchy(self):
+ class L1Cache(Cache):
+ """Simple L1 Cache with default values"""
+
+ assoc = 8
+ size = '32kB'
+ tag_latency = 1
+ data_latency = 1
+ response_latency = 1
+ mshrs = 16
+ tgts_per_mshr = 20
+ writeback_clean = True
+
+ def __init__(self):
+ super(L1Cache, self).__init__()
+
+ for cpu in self.cpu:
+ # Create a very simple cache hierarchy
+
+ # Create an L1 instruction, data and mmu cache
+ cpu.icache = L1Cache()
+ cpu.dcache = L1Cache()
+ cpu.mmucache = L1Cache()
+
+ # Connecting icache and dcache to memory bus and cpu
+ cpu.icache.mem_side = self.membus.cpu_side_ports
+ cpu.dcache.mem_side = self.membus.cpu_side_ports
+
+ cpu.icache.cpu_side = cpu.icache_port
+ cpu.dcache.cpu_side = cpu.dcache_port
+
+ # Need a new crossbar for mmucache
+
+ cpu.mmucache.mmubus = L2XBar()
+
+ cpu.mmucache.cpu_side = cpu.mmucache.mmubus.mem_side_ports
+ cpu.mmucache.mem_side = self.membus.cpu_side_ports
+
+ # Connect the itb and dtb to mmucache
+ cpu.mmu.connectWalkerPorts(
+ cpu.mmucache.mmubus.cpu_side_ports, cpu.mmucache.mmubus.cpu_side_ports)
+
+
+ def setupInterrupts(self):
+ for cpu in self.cpu:
+ # create the interrupt controller CPU and connect to the membus
+ cpu.createInterruptController()
+
+
+ def createMemoryControllerDDR3(self):
+ self.mem_cntrls = [
+ MemCtrl(dram = DDR3_1600_8x8(range = self.mem_ranges[0]),
+ port = self.membus.mem_side_ports)
+ ]
+
+ def attachIO(self, membus):
+ self.iobus = IOXBar()
+
+ self.bridge = Bridge(delay='50ns')
+ self.bridge.master = self.iobus.slave
+ self.bridge.slave = self.membus.master
+ self.bridge.ranges = self.platform._off_chip_ranges()
+
+ # Connecting on chip and off chip IO to the mem
+ # and IO bus
+ self.platform.attachOnChipIO(self.membus)
+ self.platform.attachOffChipIO(self.iobus)
+
+ def setupIntrCtrl(self):
+ self.intrctrl = IntrControl()
+
+ # Set the frequency of RTC (real time clock) used by
+ # CLINT (core level interrupt controller).
+ # This frequency is 1MHz in SiFive's U54MC.
+ # Setting it to 100MHz for faster simulation (from riscv/fs_linux.py)
+ self.platform.rtc = RiscvRTC(frequency=Frequency("100MHz"))
+
+ # RTC sends the clock signal to CLINT via an interrupt pin.
+ self.platform.clint.int_pin = self.platform.rtc.int_pin
+
+ # Attach the PLIC (platform level interrupt controller)
+ # to the platform. This initializes the PLIC with
+ # interrupt sources coming from off chip devices
+ self.platform.attachPlic()
+
+ def pmaChecker(self):
+ # From riscv/fs_linux.py
+ uncacheable_range = [
+ *self.platform._on_chip_ranges(),
+ *self.platform._off_chip_ranges()
+ ]
+ # PMA (physical memory attribute) checker is a hardware structure
+ # that ensures that physical addresses follow the memory permissions
+
+ # PMA checker can be defined at system-level (system.pma_checker)
+ # or MMU-level (system.cpu[0].mmu.pma_checker). It will be resolved
+ # by RiscvTLB's Parent.any proxy
+
+ self.pma_checker = PMAChecker(uncacheable=uncacheable_range)
+
+ def attachDisk(self, disk):
+ # VirtIOMMIO
+ image = CowDiskImage(child=RawDiskImage(read_only=True), read_only=False)
+ image.child.image_file = disk
+ # using reserved memory space
+ self.platform.disk = MmioVirtIO(
+ vio=VirtIOBlock(image=image),
+ interrupt_id=0x8,
+ pio_size = 4096,
+ pio_addr=0x10008000
+ )
diff --git a/src/riscv-fs/device.dts b/src/riscv-fs/device.dts
new file mode 100644
index 0000000..7181c6c
--- /dev/null
+++ b/src/riscv-fs/device.dts
@@ -0,0 +1,80 @@
+/dts-v1/;
+
+/ {
+ #address-cells = <0x2>;
+ #size-cells = <0x2>;
+ compatible = "riscv-virtio";
+ model = "riscv-virtio,qemu";
+
+ chosen {
+ bootargs = "root=/dev/vda ro console=ttyS0";
+ stdout-path = "/soc/uart@10000000";
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x8000000>;
+ };
+
+ cpus {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ timebase-frequency = <0x989680>;
+
+ cpu@0 {
+ phandle = <0x1>;
+ device_type = "cpu";
+ reg = <0x0>;
+ status = "okay";
+ compatible = "riscv";
+ riscv,isa = "rv64imafdcsu";
+ mmu-type = "riscv,sv48";
+
+ interrupt-controller {
+ #interrupt-cells = <0x1>;
+ interrupt-controller;
+ compatible = "riscv,cpu-intc";
+ phandle = <0x2>;
+ };
+ };
+ };
+
+ soc {
+ #address-cells = <0x2>;
+ #size-cells = <0x2>;
+ compatible = "simple-bus";
+ ranges;
+
+ uart@10000000 {
+ interrupts = <0xa>;
+ interrupt-parent = <0x3>;
+ clock-frequency = <0x384000>;
+ reg = <0x0 0x10000000 0x0 0x008>;
+ compatible = "ns8250";
+ };
+
+ plic@c000000 {
+ phandle = <0x3>;
+ riscv,ndev = <0xa>;
+ reg = <0x0 0xc000000 0x0 0x210000>;
+ interrupts-extended = <0x2 0xb 0x2 0x9>;
+ interrupt-controller;
+ compatible = "riscv,plic0";
+ #interrupt-cells = <0x1>;
+ #address-cells = <0x0>;
+ };
+
+ virtio_mmio@10008000 {
+ interrupts = <0x8>;
+ interrupt-parent = <0x3>;
+ reg = <0x0 0x10008000 0x0 0x1000>;
+ compatible = "virtio,mmio";
+ };
+
+ clint@2000000 {
+ interrupts-extended = <0x2 0x3 0x2 0x7>;
+ reg = <0x0 0x2000000 0x0 0x10000>;
+ compatible = "riscv,clint0";
+ };
+ };
+};