11#include <assert.h>
22#include <fcntl.h>
3+ #include <getopt.h>
34#include <stdio.h>
45#include <stdlib.h>
56#include <string.h>
@@ -57,6 +58,18 @@ static void emu_update_vnet_interrupts(vm_t *vm)
5758}
5859#endif
5960
61+ #if defined(ENABLE_VIRTIOBLK )
62+ static void emu_update_vblk_interrupts (vm_t * vm )
63+ {
64+ emu_state_t * data = (emu_state_t * ) vm -> priv ;
65+ if (data -> vblk .InterruptStatus )
66+ data -> plic .active |= IRQ_VBLK_BIT ;
67+ else
68+ data -> plic .active &= ~IRQ_VBLK_BIT ;
69+ plic_update_interrupts (vm , & data -> plic );
70+ }
71+ #endif
72+
6073static void mem_load (vm_t * vm , uint32_t addr , uint8_t width , uint32_t * value )
6174{
6275 emu_state_t * data = (emu_state_t * ) vm -> priv ;
@@ -85,8 +98,14 @@ static void mem_load(vm_t *vm, uint32_t addr, uint8_t width, uint32_t *value)
8598 emu_update_vnet_interrupts (vm );
8699 return ;
87100#endif
101+ #if defined(ENABLE_VIRTIOBLK )
102+ case 0x42 : /* virtio-blk */
103+ virtio_blk_read (vm , & data -> vblk , addr & 0xFFFFF , width , value );
104+ emu_update_vblk_interrupts (vm );
105+ return ;
88106 }
89107 }
108+ #endif
90109 vm_set_exception (vm , RV_EXC_LOAD_FAULT , vm -> exc_val );
91110}
92111
@@ -118,7 +137,13 @@ static void mem_store(vm_t *vm, uint32_t addr, uint8_t width, uint32_t value)
118137 emu_update_vnet_interrupts (vm );
119138 return ;
120139#endif
140+ #if defined(ENABLE_VIRTIOBLK )
141+ case 0x42 : /* virtio-blk */
142+ virtio_blk_write (vm , & data -> vblk , addr & 0xFFFFF , width , value );
143+ emu_update_vblk_interrupts (vm );
144+ return ;
121145 }
146+ #endif
122147 }
123148 vm_set_exception (vm , RV_EXC_STORE_FAULT , vm -> exc_val );
124149}
@@ -264,8 +289,67 @@ static void map_file(char **ram_loc, const char *name)
264289 close (fd );
265290}
266291
292+ static void usage (const char * execpath )
293+ {
294+ fprintf (stderr , "Usage: %s -k linux-image [-b dtb] [-d disk-image]\n" ,
295+ execpath );
296+ }
297+
298+ static void handle_options (int argc ,
299+ char * * argv ,
300+ char * * kernel_file ,
301+ char * * dtb_file ,
302+ char * * disk_file )
303+ {
304+ * kernel_file = * dtb_file = * disk_file = NULL ;
305+
306+ int optidx = 0 ;
307+ struct option opts [] = {
308+ {"kernel" , 1 , NULL , 'k' },
309+ {"dtb" , 1 , NULL , 'b' },
310+ {"disk" , 1 , NULL , 'd' },
311+ {"help" , 0 , NULL , 'h' },
312+ };
313+
314+ int c ;
315+ while ((c = getopt_long (argc , argv , "k:b:d:h" , opts , & optidx )) != -1 ) {
316+ switch (c ) {
317+ case 'k' :
318+ * kernel_file = optarg ;
319+ break ;
320+ case 'b' :
321+ * dtb_file = optarg ;
322+ break ;
323+ case 'd' :
324+ * disk_file = optarg ;
325+ break ;
326+ case 'h' :
327+ usage (argv [0 ]);
328+ exit (0 );
329+ default :
330+ break ;
331+ }
332+ }
333+
334+ if (!* kernel_file ) {
335+ fprintf (stderr ,
336+ "Linux kernel image file must "
337+ "be provided via -k option.\n" );
338+ usage (argv [0 ]);
339+ exit (2 );
340+ }
341+
342+ if (!* dtb_file )
343+ * dtb_file = "minimal.dtb" ;
344+ }
345+
267346static int semu_start (int argc , char * * argv )
268347{
348+ char * kernel_file ;
349+ char * dtb_file ;
350+ char * disk_file ;
351+ handle_options (argc , argv , & kernel_file , & dtb_file , & disk_file );
352+
269353 /* Initialize the emulator */
270354 emu_state_t emu ;
271355 memset (& emu , 0 , sizeof (emu ));
@@ -289,11 +373,11 @@ static int semu_start(int argc, char **argv)
289373
290374 char * ram_loc = (char * ) emu .ram ;
291375 /* Load Linux kernel image */
292- map_file (& ram_loc , argv [ 1 ] );
376+ map_file (& ram_loc , kernel_file );
293377 /* Load at last 1 MiB to prevent kernel / initrd from overwriting it */
294378 uint32_t dtb_addr = RAM_SIZE - 1024 * 1024 ; /* Device tree */
295379 ram_loc = ((char * ) emu .ram ) + dtb_addr ;
296- map_file (& ram_loc , ( argc == 3 ) ? argv [ 2 ] : "minimal.dtb" );
380+ map_file (& ram_loc , dtb_file );
297381 /* TODO: load disk image via virtio_blk */
298382 /* Hook for unmapping files */
299383 atexit (unmap_files );
@@ -312,6 +396,10 @@ static int semu_start(int argc, char **argv)
312396 fprintf (stderr , "No virtio-net functioned\n" );
313397 emu .vnet .ram = emu .ram ;
314398#endif
399+ #if defined(ENABLE_VIRTIOBLK )
400+ emu .vblk .ram = emu .ram ;
401+ emu .disk = virtio_blk_init (& (emu .vblk ), disk_file );
402+ #endif
315403
316404 /* Emulate */
317405 uint32_t peripheral_update_ctr = 0 ;
@@ -328,6 +416,11 @@ static int semu_start(int argc, char **argv)
328416 if (emu .vnet .InterruptStatus )
329417 emu_update_vnet_interrupts (& vm );
330418#endif
419+
420+ #if defined(ENABLE_VIRTIOBLK )
421+ if (emu .vblk .InterruptStatus )
422+ emu_update_vblk_interrupts (& vm );
423+ #endif
331424 }
332425
333426 if (vm .insn_count_hi > emu .timer_hi ||
@@ -360,9 +453,5 @@ static int semu_start(int argc, char **argv)
360453
361454int main (int argc , char * * argv )
362455{
363- if (argc < 2 ) {
364- printf ("Usage: %s <linux-image> [<dtb>]\n" , argv [0 ]);
365- return 2 ;
366- }
367456 return semu_start (argc , argv );
368457}
0 commit comments