@@ -51,6 +51,7 @@ pub enum NetworkDevice {
51
51
VirtioNetPci ,
52
52
VirtioNetMmio ,
53
53
Rtl8139 ,
54
+ GEMNet ,
54
55
}
55
56
56
57
impl Qemu {
@@ -70,13 +71,19 @@ impl Qemu {
70
71
let arg = self . sudo . then_some ( qemu. as_str ( ) ) ;
71
72
let memory = self . memory ( image_name, arch, small) ;
72
73
74
+ // GEM requires sifive_u, which in turn requires an SMP of at least 2.
75
+ let effective_smp = match self . netdev {
76
+ Some ( NetworkDevice :: GEMNet ) => usize:: max ( smp, 2 ) ,
77
+ _ => smp,
78
+ } ;
79
+
73
80
let qemu = cmd ! ( sh, "{program} {arg...}" )
74
81
. args ( & [ "-display" , "none" ] )
75
82
. args ( & [ "-serial" , "stdio" ] )
76
83
. args ( self . image_args ( image, arch) ?)
77
84
. args ( self . machine_args ( arch) )
78
85
. args ( self . cpu_args ( arch) )
79
- . args ( & [ "-smp" , & smp . to_string ( ) ] )
86
+ . args ( & [ "-smp" , & effective_smp . to_string ( ) ] )
80
87
. args ( & [ "-m" . to_string ( ) , format ! ( "{memory}M" ) ] )
81
88
. args ( & [ "-global" , "virtio-mmio.force-legacy=off" ] )
82
89
. args ( self . netdev_args ( ) )
@@ -196,9 +203,14 @@ impl Qemu {
196
203
} else if arch == Arch :: Aarch64 {
197
204
vec ! [ "-machine" . to_string( ) , "virt,gic-version=3" . to_string( ) ]
198
205
} else if arch == Arch :: Riscv64 {
206
+ // GEM requires sifive_u
207
+ let machine = match self . netdev {
208
+ Some ( NetworkDevice :: GEMNet ) => "sifive_u" ,
209
+ _ => "virt" ,
210
+ } ;
199
211
vec ! [
200
212
"-machine" . to_string( ) ,
201
- "virt" . to_string( ) ,
213
+ machine . to_string( ) ,
202
214
"-bios" . to_string( ) ,
203
215
"opensbi-1.6-rv-bin/share/opensbi/lp64/generic/firmware/fw_jump.bin" . to_string( ) ,
204
216
]
@@ -240,7 +252,12 @@ impl Qemu {
240
252
if self . accel {
241
253
todo ! ( )
242
254
} else {
243
- vec ! [ "-cpu" . to_string( ) , "rv64" . to_string( ) ]
255
+ match self . netdev {
256
+ // GEM does not seem to work with rv64 as the CPU,
257
+ // possibly because it requires sifive_u as the machine.
258
+ Some ( NetworkDevice :: GEMNet ) => vec ! [ ] ,
259
+ _ => vec ! [ "-cpu" . to_string( ) , "rv64" . to_string( ) ] ,
260
+ }
244
261
}
245
262
}
246
263
}
@@ -265,34 +282,45 @@ impl Qemu {
265
282
}
266
283
267
284
fn netdev_args ( & self ) -> Vec < String > {
268
- let Some ( netdev) = self . netdev else {
269
- return vec ! [ ] ;
270
- } ;
285
+ const NETDEV_OPTIONS : & str = "user,id=u1,hostfwd=tcp::9975-:9975,hostfwd=udp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9" ;
286
+ match self . netdev {
287
+ Some ( NetworkDevice :: GEMNet ) => {
288
+ vec ! [
289
+ "-nic" . to_string( ) ,
290
+ format!( "{NETDEV_OPTIONS},model=cadence_gem" ) ,
291
+ ]
292
+ }
293
+ Some ( netdev) => {
294
+ let mut netdev_args = vec ! [
295
+ "-netdev" . to_string( ) ,
296
+ NETDEV_OPTIONS . to_string( ) ,
297
+ "-device" . to_string( ) ,
298
+ ] ;
299
+
300
+ let mut device_arg = match netdev {
301
+ NetworkDevice :: VirtioNetPci => "virtio-net-pci,netdev=u1,disable-legacy=on" ,
302
+ NetworkDevice :: VirtioNetMmio => "virtio-net-device,netdev=u1" ,
303
+ NetworkDevice :: Rtl8139 => "rtl8139,netdev=u1" ,
304
+ NetworkDevice :: GEMNet => {
305
+ unreachable ! ( "We should have already checked for GEM earlier." )
306
+ }
307
+ }
308
+ . to_string ( ) ;
309
+
310
+ if !self . no_default_virtio_features
311
+ && matches ! (
312
+ netdev,
313
+ NetworkDevice :: VirtioNetPci | NetworkDevice :: VirtioNetMmio
314
+ ) {
315
+ device_arg. push_str ( ",packed=on,mq=on" ) ;
316
+ }
271
317
272
- let mut netdev_args = vec ! [
273
- "-netdev" . to_string( ) ,
274
- "user,id=u1,hostfwd=tcp::9975-:9975,hostfwd=udp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9" . to_string( ) ,
275
- "-device" . to_string( ) ,
276
- ] ;
318
+ netdev_args. push ( device_arg) ;
277
319
278
- let mut device_arg = match netdev {
279
- NetworkDevice :: VirtioNetPci => "virtio-net-pci,netdev=u1,disable-legacy=on" ,
280
- NetworkDevice :: VirtioNetMmio => "virtio-net-device,netdev=u1" ,
281
- NetworkDevice :: Rtl8139 => "rtl8139,netdev=u1" ,
282
- }
283
- . to_string ( ) ;
284
-
285
- if !self . no_default_virtio_features
286
- && matches ! (
287
- netdev,
288
- NetworkDevice :: VirtioNetPci | NetworkDevice :: VirtioNetMmio
289
- ) {
290
- device_arg. push_str ( ",packed=on,mq=on" ) ;
320
+ netdev_args
321
+ }
322
+ None => vec ! [ ] ,
291
323
}
292
-
293
- netdev_args. push ( device_arg) ;
294
-
295
- netdev_args
296
324
}
297
325
298
326
fn virtiofsd_args ( & self , memory : usize ) -> Vec < String > {
0 commit comments