Skip to content

Conversation

ChinYikMing
Copy link
Collaborator

@ChinYikMing ChinYikMing commented Aug 30, 2025

Demo Video

multiple-vblk.mp4

Problem Statement

Previously, #539 set VBLK_DEV_CNT_MAX to 1, limiting the virtual
machine to a single block device. This commit introduces support for
multiple block devices by switching from statically allocated storage to
dynamic allocation based on CLI input.

Key changes:

  1. Dynamic Allocation
    Virtio block related fields are now dynamically allocated based on the
    number of -x vblk options provided.

  2. Device Tree Generation
    The prewritten virtio@ subnode for block device in device/minimal.dts is
    commented and it can be an example subnode for future reference.
    load_dtb() dynamically appends virtio@ subnodes under the SoC node
    based on the number of block devices.

  3. MMIO Handling
    Instead of hardcoding switch cases for each MMIO region of block device,
    the code now checks whether the accessed MMIO address falls within the
    valid range of any block device.

Note:
The /dev/vdx device order is assigned in reverse: the first -x vblk
argument corresponds to the device with the highest letter, while
subsequent arguments receive lower-lettered device names.

Testing Procedure

  1. Clone the branch
$ git clone https://github.com/ChinYikMing/rv32emu.git -b multiple-vblk --depth 1 && cd rv32emu
  1. Create 2 disk images (more than 2 is also OK, just adjusting the -x vblk option)
$ dd if=/dev/zero of=disk1.img bs=4M count=32
$ mkfs.ext4 disk1.img

$ dd if=/dev/zero of=disk2.img bs=4M count=32
$ mkfs.ext4 disk2.img
  1. Build the emulator
$ make ENABLE_SYSTEM=1 INITRD_SIZE=32 -j8
  1. Fetch Linux Image artifact
$ make artifact ENABLE_SYSTEM=1
  1. Boot the guestOS with 2 block devices
$ build/rv32emu -k build/linux-image/Image -i build/linux-image/rootfs.cpio -x vblk:disk1.img -x vblk:disk2.img
  1. Show multiple block devices in guestOS
# ls /dev/vd*
  1. Mount both block devices in guestOS
# mkdir -p mnt && mount /dev/vda mnt
# mkdir -p mnt2 && mount /dev/vdb mnt2
  1. Write some data into the block devices
# echo "rv32emu" > mnt/emu.txt
# echo "rv32emu" > mnt2/emu.txt
  1. Cat the written data in the block devices
# cat mnt/emu.txt
# cat mnt2/emu.txt

Expected Result

# ls /dev/vd*
/dev/vda  /dev/vdb
# mkdir -p mnt && mount /dev/vda mnt
[   30.911107] EXT4-fs (vda): mounted filesystem with ordered data mode. Quota mode: disabled.
# mkdir -p mnt2 && mount /dev/vdb mnt2
[   39.067705] EXT4-fs (vdb): mounted filesystem with ordered data mode. Quota mode: disabled.
# echo "rv32emu" > mnt/emu.txt
# echo "rv32emu" > mnt2/emu.txt
# cat mnt/emu.txt
rv32emu
# cat mnt2/emu.txt
rv32emu
#

Copy link
Contributor

@jserv jserv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmarks

Benchmark suite Current: 9b4f2fe Previous: 678c47a Ratio
Dhrystone 1323 Average DMIPS over 10 runs 1290 Average DMIPS over 10 runs 0.98
Coremark 904.68 Average iterations/sec over 10 runs 913.951 Average iterations/sec over 10 runs 1.01

This comment was automatically generated by workflow using github-action-benchmark.

src/riscv.c Outdated
#define DTB_EXPAND_SIZE 1024 /* or more if needed */

/* Allocate enough memory for DTB + extra room */
int minimal_len = ARRAY_SIZE(minimal);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Since this variable represents a length, would size_t be more appropriate than int?

Previously, sysprog21#539 set VBLK_DEV_CNT_MAX to 1, limiting the virtual
machine to a single block device. This commit introduces support for
multiple block devices by switching from statically allocated storage to
dynamic allocation based on CLI input.

Key changes:
1. Dynamic Allocation
Virtio block related fields are now dynamically allocated based on the
number of -x vblk options provided.

2. Device Tree Generation
The prewritten virtio@ subnode for block device in device/minimal.dts is
commented and it can be an example subnode for future reference.
load_dtb() dynamically appends virtio@ subnodes under the SoC node
based on the number of block devices.

3. MMIO Handling
Instead of hardcoding switch cases for each MMIO region of block device,
the code now checks whether the accessed MMIO address falls within the
valid range of any block device.

Note:
The /dev/vdx device order is assigned in reverse: the first -x vblk
argument corresponds to the device with the highest letter, while
subsequent arguments receive lower-lettered device names.
To reflect supporting multiple virtual block devices in guestOS.
This commit prevents null terminator at wrong position.
@ChinYikMing

This comment was marked as duplicate.

@ChinYikMing
Copy link
Collaborator Author

ChinYikMing commented Sep 19, 2025

@jserv , please rerun the macOS CI to resolve the JIT test failure.

I'm not sure if you could relax the rerun specific CI permission to collaborators so we can quickly rerun it when needed in the future.

@jserv jserv merged commit ccdcc30 into sysprog21:master Sep 20, 2025
86 of 100 checks passed
@jserv
Copy link
Contributor

jserv commented Sep 20, 2025

Thank @ChinYikMing for contributing!

@ChinYikMing ChinYikMing deleted the multiple-vblk branch September 21, 2025 05:51
ChinYikMing added a commit to ChinYikMing/rv32emu that referenced this pull request Sep 21, 2025
The system date after boot is not synchronized with the host's wall
clock, resulting in incorrect timestamps shown by commands such as date.
When the system has the hwclock utility, it cannot function because
the /dev/rtc? device file is missing. In addition, programs might rely
on RTC alarm events for wake-up operations, which require access to
/dev/rtc? device file.

This commit implements an RTC device using the Goldfish RTC model,
chosen for its simplicity and native support in the Linux kernel.

By adding RTC support, the following capabilities are enabled:
- System boot-up synchronization: The RTC driver initializes the
  system time from the at boot, ensuring the guestOS starts with an
  accurate and synchronized timestamp.
- Wakeup events: The RTC can generate alarm interrupts to wake up the
  process.
- The date command, hwclock utility, and alarm configuration via ioctl
  (see the rtc(4) man page) are now functional.
- Provide accurate timestamps for filesystem operations such as when
  writing or modifying files on a virtio block device.

The sysprog21#605 hardcoded vblk_mmio_base_hi to 0x41, which limits adding new
subnodes (e.g., RTC) under the SoC node. This value should instead be
dynamically set during load_dtb(). Another limitation is in the
next_addr probing logic, which currently uses subnode's name + 7. This
assumes a fixed-length name and fails for variable-length names (e.g.,
rtc@4100000, should be name + 4). The fix is to locate the '@' character
in the subnode name and use its position + 1 as the offset.
Additionally, when no virtio block device is specified,
virtio_mmio_base_hi will default to 0. In this case, use vblk_cnt for
condition checking during MMIO handling to avoid incorrect behavior.
ChinYikMing added a commit to ChinYikMing/rv32emu that referenced this pull request Sep 21, 2025
The system date after boot is not synchronized with the host's wall
clock, resulting in incorrect timestamps shown by commands such as date.
When the system has the hwclock utility, it cannot function because
the /dev/rtc? device file is missing. In addition, programs might rely
on RTC alarm events for wake-up operations, which require access to
/dev/rtc? device file.

This commit implements an RTC device using the Goldfish RTC model,
chosen for its simplicity and native support in the Linux kernel.

By adding RTC support, the following capabilities are enabled:
- System boot-up synchronization: The RTC driver initializes the
  system time from the at boot, ensuring the guestOS starts with an
  accurate and synchronized timestamp.
- Wakeup events: The RTC can generate alarm interrupts to wake up the
  process.
- The date command, hwclock utility, and alarm configuration via ioctl
  (see the rtc(4) man page) are now functional.
- Provide accurate timestamps for filesystem operations such as when
  writing or modifying files on a virtio block device.

The sysprog21#605 hardcoded vblk_mmio_base_hi to 0x41, which limits adding new
subnodes (e.g., RTC) under the SoC node. This value should instead be
dynamically set during load_dtb(). Another limitation is in the
next_addr probing logic, which currently uses subnode's name + 7. This
assumes a fixed-length name and fails for variable-length names (e.g.,
rtc@4100000, should be name + 4). The fix is to locate the '@' character
in the subnode name and use its position + 1 as the offset.
Additionally, when no virtio block device is specified,
virtio_mmio_base_hi will default to 0. In this case, use vblk_cnt for
condition checking during MMIO handling to avoid incorrect behavior.
@jserv jserv added this to the release-2025.2 milestone Oct 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants