Skip to content

Commit ccdcc30

Browse files
authored
Merge pull request #605 from ChinYikMing/multiple-vblk
Support multiple virtio block devices
2 parents 56120c0 + 9b4f2fe commit ccdcc30

File tree

10 files changed

+281
-134
lines changed

10 files changed

+281
-134
lines changed

.ci/boot-linux.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ if [ "${ENABLE_VBLK}" -eq "1" ]; then
6161
expect "# " { send "\x01"; send "x" } timeout { exit 3 }
6262
')
6363

64+
# multiple blocks, Read-only, one disk image, one loop device (/dev/loopx(Linux) or /dev/diskx(Darwin))
65+
TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${VBLK_IMG},readonly -x vblk:${BLK_DEV},readonly")
66+
EXPECT_CMDS+=('
67+
expect "buildroot login:" { send "root\n" } timeout { exit 1 }
68+
expect "# " { send "uname -a\n" } timeout { exit 2 }
69+
expect "riscv32 GNU/Linux" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 }
70+
expect "# " { send "echo rv32emu > mnt/emu.txt\n" } timeout { exit 3 }
71+
expect -ex "-sh: can'\''t create mnt/emu.txt: Read-only file system" {} timeout { exit 3 }
72+
expect "# " { send "mkdir mnt2 && mount /dev/vdb mnt2\n" } timeout { exit 3 }
73+
expect "# " { send "echo rv32emu > mnt2/emu.txt\n" } timeout { exit 3 }
74+
expect -ex "-sh: can'\''t create mnt2/emu.txt: Read-only file system" {} timeout { exit 3 }
75+
expect "# " { send "\x01"; send "x" } timeout { exit 3 }
76+
')
77+
6478
# Read-write using disk image
6579
TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${VBLK_IMG}")
6680
VBLK_EXPECT_CMDS='
@@ -77,6 +91,23 @@ if [ "${ENABLE_VBLK}" -eq "1" ]; then
7791
# Read-write using /dev/loopx(Linux) or /dev/diskx(Darwin) block device
7892
TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${BLK_DEV}")
7993
EXPECT_CMDS+=("${VBLK_EXPECT_CMDS}")
94+
95+
# multiple blocks, Read-write, one disk image and one loop device (/dev/loopx(Linux) or /dev/diskx(Darwin))
96+
TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${VBLK_IMG} -x vblk:${BLK_DEV}")
97+
VBLK_EXPECT_CMDS='
98+
expect "buildroot login:" { send "root\n" } timeout { exit 1 }
99+
expect "# " { send "uname -a\n" } timeout { exit 2 }
100+
expect "riscv32 GNU/Linux" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 }
101+
expect "# " { send "echo rv32emu > mnt/emu.txt\n" } timeout { exit 3 }
102+
expect "# " { send "sync\n" } timeout { exit 3 }
103+
expect "# " { send "umount mnt\n" } timeout { exit 3 }
104+
expect "# " { send "mkdir mnt2 && mount /dev/vdb mnt2\n" } timeout { exit 3 }
105+
expect "# " { send "echo rv32emu > mnt2/emu.txt\n" } timeout { exit 3 }
106+
expect "# " { send "sync\n" } timeout { exit 3 }
107+
expect "# " { send "umount mnt2\n" } timeout { exit 3 }
108+
expect "# " { send "\x01"; send "x" } timeout { exit 3 }
109+
'
110+
EXPECT_CMDS+=("${VBLK_EXPECT_CMDS}")
80111
fi
81112

82113
for i in "${!TEST_OPTIONS[@]}"; do

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ Mount the virtual block device and create a test file after booting, note that r
105105
```
106106
Reboot and re-mount the virtual block device, the written file should remain existing.
107107
108+
To specify multiple virtual block devices, pass multiple `-x vblk` options when launching the emulator. Each option can point to either a disk image or a hostOS block device, with optional read-only mode. For example:
109+
```shell
110+
$ build/rv32emu -k <kernel_img_path> -i <rootfs_img_path> -x vblk:disk.img -x vblk:/dev/loop22,readonly
111+
```
112+
Note that the /dev/vdx device order in guestOS 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.
113+
108114
#### Customize bootargs
109115
Build and run with customized bootargs to boot the guestOS. Otherwise, the default bootargs defined in `src/devices/minimal.dts` will be used.
110116
```shell

src/devices/minimal.dts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,14 @@
6666
clock-frequency = <5000000>; /* the baudrate divisor is ignored */
6767
};
6868

69-
blk0: virtio@4200000 {
69+
/*
70+
* Virtio block example subnode
71+
* The actual subnode are generated dynamically depends on the CLI -x vblk option
72+
*/
73+
/*blk0: virtio@4100000 {
7074
compatible = "virtio,mmio";
71-
reg = <0x4200000 0x200>;
72-
interrupts = <3>;
73-
};
75+
reg = <0x4100000 0x200>;
76+
interrupts = <2>;
77+
};*/
7478
};
7579
};

src/devices/virtio-blk.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@
3232

3333
#define DISK_BLK_SIZE 512
3434

35-
/* TODO: Enable mutiple virtio-blk devices. */
36-
#define VBLK_DEV_CNT_MAX 1
37-
3835
#define VBLK_FEATURES_0 0
3936
#define VBLK_FEATURES_1 1 /* VIRTIO_F_VERSION_1 */
4037
#define VBLK_QUEUE_NUM_MAX 1024
@@ -81,9 +78,6 @@ PACKED(struct vblk_req_header {
8178
uint8_t status;
8279
});
8380

84-
static struct virtio_blk_config vblk_configs[VBLK_DEV_CNT_MAX];
85-
static int vblk_dev_cnt = 0;
86-
8781
static void virtio_blk_set_fail(virtio_blk_state_t *vblk)
8882
{
8983
vblk->status |= VIRTIO_STATUS_DEVICE_NEEDS_RESET;
@@ -401,20 +395,16 @@ uint32_t *virtio_blk_init(virtio_blk_state_t *vblk,
401395
char *disk_file,
402396
bool readonly)
403397
{
404-
if (vblk_dev_cnt >= VBLK_DEV_CNT_MAX) {
405-
rv_log_error(
406-
"Exceeded the number of virtio-blk devices that can be allocated");
407-
exit(EXIT_FAILURE);
408-
}
409-
410398
/*
411399
* For mmap_fallback, if vblk is not specified, disk_fd should remain -1 and
412400
* no fsync should be performed on exit.
413401
*/
402+
414403
vblk->disk_fd = -1;
415404

416405
/* Allocate memory for the private member */
417-
vblk->priv = &vblk_configs[vblk_dev_cnt++];
406+
vblk->priv = calloc(1, sizeof(struct virtio_blk_config));
407+
assert(vblk->priv);
418408

419409
/* No disk image is provided */
420410
if (!disk_file) {
@@ -549,5 +539,6 @@ void vblk_delete(virtio_blk_state_t *vblk)
549539
else
550540
munmap(vblk->disk, VBLK_PRIV(vblk)->disk_size);
551541
#endif
542+
free(vblk->priv);
552543
free(vblk);
553544
}

src/devices/virtio.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ struct virtq_desc {
7676
uint16_t next;
7777
};
7878

79-
#define IRQ_VBLK_SHIFT 3
80-
#define IRQ_VBLK_BIT (1 << IRQ_VBLK_SHIFT)
79+
#define IRQ_VBLK_BIT(base, i) (1 << (base + i))
8180

8281
typedef struct {
8382
uint32_t queue_num;

src/main.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ static char *prof_out_file;
6060
static char *opt_kernel_img;
6161
static char *opt_rootfs_img;
6262
static char *opt_bootargs;
63-
static char *opt_virtio_blk_img;
63+
/* FIXME: handle overflow */
64+
#define VBLK_DEV_MAX 100
65+
static char *opt_virtio_blk_img[VBLK_DEV_MAX];
66+
static int opt_virtio_blk_idx = 0;
6467
#endif
6568

6669
static void print_usage(const char *filename)
@@ -78,8 +81,10 @@ static void print_usage(const char *filename)
7881
#if RV32_HAS(SYSTEM) && !RV32_HAS(ELF_LOADER)
7982
" -k <image> : use <image> as kernel image\n"
8083
" -i <image> : use <image> as rootfs\n"
81-
" -x vblk:<image>[,readonly] : use <image> as virtio-blk disk image "
82-
"(default read and write)\n"
84+
" -x vblk:<image>[,readonly]: use "
85+
"<image> as virtio-blk disk image "
86+
"(default read and write). This option may be specified "
87+
"multiple times for multiple block devices\n"
8388
" -b <bootargs> : use customized <bootargs> for the kernel\n"
8489
#endif
8590
" -d [filename]: dump registers as JSON to the "
@@ -127,7 +132,8 @@ static bool parse_args(int argc, char **args)
127132
break;
128133
case 'x':
129134
if (!strncmp("vblk:", optarg, 5))
130-
opt_virtio_blk_img = optarg + 5; /* strlen("vblk:") */
135+
opt_virtio_blk_img[opt_virtio_blk_idx++] =
136+
optarg + 5; /* strlen("vblk:") */
131137
else
132138
return false;
133139
emu_argc++;
@@ -273,7 +279,12 @@ int main(int argc, char **args)
273279
attr.data.system.kernel = opt_kernel_img;
274280
attr.data.system.initrd = opt_rootfs_img;
275281
attr.data.system.bootargs = opt_bootargs;
276-
attr.data.system.vblk_device = opt_virtio_blk_img;
282+
if (opt_virtio_blk_idx) {
283+
attr.data.system.vblk_device = opt_virtio_blk_img;
284+
attr.data.system.vblk_device_cnt = opt_virtio_blk_idx;
285+
} else {
286+
attr.data.system.vblk_device = NULL;
287+
}
277288
#else
278289
attr.data.user.elf_program = opt_prog_name;
279290
#endif

0 commit comments

Comments
 (0)