-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement VirtIO block device #539
Conversation
There was a problem hiding this 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: fd051c2 | Previous: caef4ad | Ratio |
---|---|---|---|
Dhrystone |
1299 Average DMIPS over 10 runs |
1336 Average DMIPS over 10 runs |
1.03 |
Coremark |
959.33 Average iterations/sec over 10 runs |
974.943 Average iterations/sec over 10 runs |
1.02 |
This comment was automatically generated by workflow using github-action-benchmark.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Specify Shengwen Cheng as co-author in git commit messages. See https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors
- Consolidate GitHub Actions to automate virtio-blk test procedure.
Does it have any instructions / documentations for demonstrating or testing of this newly added feature? |
rv32emu use |
@vacantron @ChinYikMing Thank you for the insightful comments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change the description of this pull request, adding information for others to build the system emulator and test the virtio-blk feature. This will make it easier for others to access the information without needing to refer to the README but also keep them in README :) .
Compilation warnings reported by GCC:
Simply add |
cb15ab4
to
f513ee7
Compare
@@ -118,6 +120,13 @@ static bool parse_args(int argc, char **args) | |||
opt_bootargs = optarg; | |||
emu_argc++; | |||
break; | |||
case 'x': | |||
if (!strncmp("vblk:", optarg, 5)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why must we introduce such complexity with the vblk:
prefix? The brilliant way is to use just the disk file name here and consider adding the long option for different block devices if required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why must we introduce such complexity with the
vblk:
prefix?
VirtIO features like disk, network, and sound can be dynamically enabled using the -x
option, inspired by Oracle/Sun Java virtual machine. For example: -x vblk:<disk> -x vnet:tap0 -x vsnd:alsa
. The long command options might be confusing if we want to specify more VirtIO devices, such as a secondary virtio-blk.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. Thanks
|
||
/* virtio-blk device */ | ||
uint32_t *disk; | ||
virtio_blk_state_t *vblk; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok it seems like UART and VIRTIO_BLK come from semu, and PLIC may have a little bit different design here......
I am just thinking of wrapping these things in virtio_blk_t
, but maybe we can refactor these in other PR if required. This is not a critical issue.
.ci/boot-linux.sh
Outdated
ENABLE_VBLK=1 | ||
type dd >/dev/null 2>&1 || ENABLE_VBLK=0 | ||
(type mkfs.ext4 >/dev/null 2>&1 || type $(brew --prefix e2fsprogs)/sbin/mkfs.ext4) >/dev/null 2>&1 || ENABLE_VBLK=0 | ||
type 7z >/dev/null 2>&1 || ENABLE_VBLK=0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is 7z required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe using 7z
to list files in disk.img
is the simplest and most efficient method to verify whether the file emu.txt
written by the guest OS exists.
Other approaches have limitations:
- Mounting
disk.img
requires root privileges, which may not always be feasible. - Inspecting the image with
debugfs
provides the desired result but involves navigating a complex interactive interface. dumpe2fs
fail with an error, "Wrong magic number for Ext2 Image Header while trying to open disk.img" when attempting to processdisk.img
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we simply use cpio
or ar
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we simply use
cpio
orar
instead?
Neither cpio
, ar
nor zcat
recognizes the image file, and after a quick review of their man pages, I couldn’t find any useful options to address this issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can verify the success of filesystem creation by checking the return code from mkfs.ext4
directly, rather than using additional tools like 7z. Since 7z is not included in standard Linux distributions, avoiding such external dependencies makes the testing process more accessible to other developers and simplifies collaboration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can verify the success of filesystem creation by checking the return code from
mkfs.ext4
directly, rather than using additional tools like 7z. Since 7z is not included in standard Linux distributions, avoiding such external dependencies makes the testing process more accessible to other developers and simplifies collaboration.
I completely agree that avoiding extra tools like 7z
would significantly improve portability and make the testing process more accessible. However, checkin the return code of mkfs.ext4
merely verifies that the filesystem was created, but it does not confirm that Virtio-blk is functioning correctly.
For example:
$ dd if=/dev/zero of=disk.img bs=4M count=32
32+0 records in
32+0 records out
134217728 bytes (134 MB, 128 MiB) copied, 0.314109 s, 427 MB/s
$ mkfs.ext4 disk.img
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done
Creating filesystem with 32768 4k blocks and 32768 inodes
Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done
$ mkfs.ext4 disk.img
mke2fs 1.47.0 (5-Feb-2023)
disk.img contains a ext4 file system
created on Mon Jan 27 23:22:21 2025
Proceed anyway? (y,N) n
$ echo $?
1
As shown above, the second call to mkfs.ext4 returns 1 because the filesystem was already created by the first call, even though the emulator was never started.
|
||
#define DISK_BLK_SIZE 512 | ||
|
||
#define VBLK_DEV_CNT_MAX 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, does this refer to the virtio block limit? I believe it can attach multiple virtual block devices, can't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, does this refer to the virtio block limit? I believe it can attach multiple virtual block devices, can't it?
Certainly, multiple virtual block devices can be attached. However, after a quick review, it appears that each vblk
device requires an independent virtqueue at least. Additionally, unlike QEMU, rv32emu’s current implementation uses a hardcoded device tree at build time. This could lead to significant complications with MMIO register mapping and negatively impact performance due to the extra polling required.
If possible, I would prefer to leave this for future extension, when the device tree and MMIO mapping can be adjusted at runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to leave this for future extension, when the device tree and MMIO mapping can be adjusted at runtime.
Add corresponding FIXME/TODO comments.
.ci/boot-linux.sh
Outdated
TIMEOUT=50 | ||
OPTS=" -k build/linux-image/Image " | ||
OPTS+=" -i build/linux-image/rootfs.cpio " | ||
OPTS+=" -b build/minimal.dtb " | ||
if [ "$ENABLE_VBLK" -eq "1" ]; then | ||
dd if=/dev/zero of=build/disk.img bs=4M count=32 | ||
mkfs.ext4 build/disk.img || $(brew --prefix e2fsprogs)/sbin/mkfs.ext4 build/disk.img |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No macOS CI is integrated yet. Is it suitable to include brew utility since we do not actually use it for now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was added based on this review. While we do not currently utilize the brew utility, its inclusion is harmless and imposes minimal runtime overhead.
.ci/boot-linux.sh
Outdated
@@ -16,31 +16,62 @@ function ASSERT { | |||
|
|||
cleanup | |||
|
|||
ENABLE_VBLK=1 | |||
type dd >/dev/null 2>&1 || ENABLE_VBLK=0 | |||
(type mkfs.ext4 >/dev/null 2>&1 || type $(brew --prefix e2fsprogs)/sbin/mkfs.ext4) >/dev/null 2>&1 || ENABLE_VBLK=0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
src/devices/virtio.h
Outdated
}; | ||
|
||
struct virtq_desc { | ||
uint32_t addr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to Virtual I/O Device (VIRTIO) Version 1.3
2.7.5 The Virtqueue Descriptor Table
struct virtq_desc {
/* Address (guest-physical). */
le64 addr;
/* Length. */
le32 len;
/* The flags as indicated above. */
le16 flags;
/* We chain unused descriptors via this, too */
le16 next;
};
We mistakenly defined virtq_desc.addr
as 32 bits.
Please consider correcting it here and submitting a pull request for semu.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rebase the latest master branch to resolve Arm64 host breakage on CI.
8583029
to
bce4c85
Compare
HELP WANTED I found that the current implementation is incorrect when I am currently not in Tainan and do not have access to an MSVC environment. Therefore, I am unsure whether this is a bug or if |
MSVC support can be disregarded as it is not functional. While initial testing was performed on Windows 8 during the my original code snapshot in 2020, there has never been a working Windows build of rv32emu. Of course, if you are interested in a Windows port, pull requests are always welcome. At present, concentrate on the condition |
.ci/boot-linux.sh
Outdated
if [ "$ENABLE_VBLK" -eq "1" ]; then | ||
dd if=/dev/zero of=build/disk.img bs=4M count=32 | ||
mkfs.ext4 build/disk.img || $(brew --prefix e2fsprogs)/sbin/mkfs.ext4 build/disk.img | ||
OPTS+=" -x vblk:build/disk.img " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
build/disk.img
is repeated in the changes. Replace them with a variable such as VBLK_IMG=build/disk.img
and access it via $(VBLK_IMG)
.
.ci/boot-linux.sh
Outdated
printf "\nBoot Linux Test: [ ${COLOR_G}${MESSAGES[$ret]}${COLOR_N} ]\n" | ||
if [ "$ENABLE_VBLK" -eq "1" ]; then | ||
file_list=$(7z l build/disk.img) | ||
(echo $file_list | grep emu.txt >/dev/null 2>&1) || ret=4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since file_list
is only accessed here, is it better to streamline them into one line by removing file_list
variable?
5770932
to
d0ecf72
Compare
ret=$? | ||
cleanup | ||
|
||
MESSAGES=("OK!" \ | ||
"Fail to boot" \ | ||
"Fail to login" \ | ||
"Fail to run commands" \ | ||
"Fail to find emu.txt in $VBLK_IMG"\ | ||
) | ||
|
||
COLOR_G='\e[32;01m' # Green |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Introduce red color here such that: COLOR_R='\e[31;01m' # Red
.ci/boot-linux.sh
Outdated
printf "\nBoot Linux Test: [ ${COLOR_G}${MESSAGES[$ret]}${COLOR_N} ]\n" | ||
if [ "$ENABLE_VBLK" -eq "1" ]; then | ||
7z l $VBLK_IMG | grep emu.txt >/dev/null 2>&1 || ret=4 | ||
printf "Virtio-blk Test: [ ${COLOR_G}${MESSAGES[$ret]}${COLOR_N} ]\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Show the VirtIO block error message (ret=4) in red instead of green since it is typically used for success.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Show the VirtIO block error message (ret=4) in red instead of green since it is typically used for success.
Shall other error messages be changed into red as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Show the VirtIO block error message (ret=4) in red instead of green since it is typically used for success.
Shall other error messages be changed into red as well?
Yes, let's make them consistent. Thanks!
803d241
to
caef4ad
Compare
This comment was marked as resolved.
This comment was marked as resolved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rebase the latest master
branch and fix conflicts.
This commit migrates @shengwen-tw's brilliant virtio implementation from semu, with the following modification: 1. Rename virtio_blk_reg_read/write to virtio_blk_read/write The original virtio_blk_read verified whether the virtio MMIO was aligned to 4. Since rv32emu does not enforce alignment checks for UART and PLIC devices or raise misalignment exceptions, this verification has been omitted. 2. Implement MMIO_VIRTIOBLK 3. Implement vblk_new() and vblk_delete() These functions align with the conventions used for UART and PLIC devices. 4. Introduce new argument '-x vblk:<disk_image>' for virtio-blk disk image 5. Fix the size of addr in virtq_desc structure. Co-authored-by: Shengwen Cheng <[email protected]>
Virtio-blk verification has been integrated into boot-linux test, and is enabled by default. The p7zip-full package, providing command '7z', is added to dependencies in order to validate the success of writes to the Virtio-blk device. This commit also removes -b argument when starting the emulator, as it is refined to be used to accept custom bootargs.
Thank @otteryc for contributing! |
This commit migrates @shengwen-tw's brilliant virtio implementation from semu, with the following modification:
Rename virtio_blk_reg_read/write to virtio_blk_read/write The original virtio_blk_read verified whether the virtio MMIO was aligned to 4. Since rv32emu does not enforce alignment checks for UART and PLIC devices or raise misalignment exceptions, this verification has been omitted.
Implement MMIO_VIRTIOBLK
Implement vblk_new() and vblk_delete()
These functions align with the conventions used for UART and PLIC devices.
Introduce new argument '-x vblk:<disk_image>' for virtio-blk disk image
This pull request has been tested on:
To try out virtio-blk:
Generate ext4 image file for virtio block device in Unix-like system:
Boot the Guest OS
Mount the virtual block device and create a test file after booting:
Reboot the system and re-mount the virtual block device, the written file should remain existing.