@@ -23,6 +23,19 @@ use std::sync::atomic::Ordering;
23
23
use std:: sync:: Arc ;
24
24
use vmcore:: line_interrupt:: LineInterrupt ;
25
25
26
+ const SUPPORTED_COMMAND_BITS : u16 = cfg_space:: Command :: new ( )
27
+ . with_pio_enabled ( true )
28
+ . with_mmio_enabled ( true )
29
+ . with_bus_master ( true )
30
+ . with_special_cycles ( true )
31
+ . with_enable_memory_write_invalidate ( true )
32
+ . with_vga_palette_snoop ( true )
33
+ . with_parity_error_response ( true )
34
+ . with_enable_serr ( true )
35
+ . with_enable_fast_b2b ( true )
36
+ . with_intx_disable ( true )
37
+ . into_bits ( ) ;
38
+
26
39
/// A wrapper around a [`LineInterrupt`] that considers PCI configuration space
27
40
/// interrupt control bits.
28
41
#[ derive( Debug , Inspect ) ]
@@ -98,7 +111,7 @@ impl ConfigSpaceType0EmulatorState {
98
111
fn new ( ) -> Self {
99
112
Self {
100
113
latency_timer : 0 ,
101
- command : cfg_space:: Command :: empty ( ) ,
114
+ command : cfg_space:: Command :: new ( ) ,
102
115
base_addresses : [ 0 ; 6 ] ,
103
116
interrupt_line : 0 ,
104
117
}
@@ -247,7 +260,9 @@ impl ConfigSpaceType0Emulator {
247
260
const MIN_BAR_SIZE : u64 = 4096 ;
248
261
let len = std:: cmp:: max ( len. next_power_of_two ( ) , MIN_BAR_SIZE ) ;
249
262
let mask64 = !( len - 1 ) ;
250
- bar_masks[ bar_index] = mask64 as u32 | cfg_space:: BarEncodingBits :: TYPE_64_BIT . bits ( ) ;
263
+ bar_masks[ bar_index] = cfg_space:: BarEncodingBits :: from_bits ( mask64 as u32 )
264
+ . with_type_64_bit ( true )
265
+ . into_bits ( ) ;
251
266
bar_masks[ bar_index + 1 ] = ( mask64 >> 32 ) as u32 ;
252
267
mapped_memory[ bar_index] = Some ( mapped) ;
253
268
}
@@ -264,7 +279,7 @@ impl ConfigSpaceType0Emulator {
264
279
intx_interrupt : None ,
265
280
266
281
state : ConfigSpaceType0EmulatorState {
267
- command : cfg_space:: Command :: empty ( ) ,
282
+ command : cfg_space:: Command :: new ( ) ,
268
283
base_addresses : [ 0 ; 6 ] ,
269
284
interrupt_line : 0 ,
270
285
latency_timer : 0 ,
@@ -332,18 +347,16 @@ impl ConfigSpaceType0Emulator {
332
347
( self . hardware_ids . device_id as u32 ) << 16 | self . hardware_ids . vendor_id as u32
333
348
}
334
349
HeaderType00 :: STATUS_COMMAND => {
335
- let mut status = cfg_space:: Status :: empty ( ) ;
336
- if !self . capabilities . is_empty ( ) {
337
- status |= cfg_space:: Status :: CAPABILITIES_LIST ;
338
- }
350
+ let mut status =
351
+ cfg_space:: Status :: new ( ) . with_capabilities_list ( !self . capabilities . is_empty ( ) ) ;
339
352
340
353
if let Some ( intx_interrupt) = & self . intx_interrupt {
341
354
if intx_interrupt. interrupt_status . load ( Ordering :: SeqCst ) {
342
- status |= cfg_space :: Status :: INTERRUPT_STATUS ;
355
+ status. set_interrupt_status ( true ) ;
343
356
}
344
357
}
345
358
346
- ( status. bits ( ) as u32 ) << 16 | self . state . command . bits ( ) as u32
359
+ ( status. into_bits ( ) as u32 ) << 16 | self . state . command . into_bits ( ) as u32
347
360
}
348
361
HeaderType00 :: CLASS_REVISION => {
349
362
( u8:: from ( self . hardware_ids . base_class ) as u32 ) << 24
@@ -436,12 +449,12 @@ impl ConfigSpaceType0Emulator {
436
449
437
450
fn update_intx_disable ( & mut self , command : cfg_space:: Command ) {
438
451
if let Some ( intx_interrupt) = & self . intx_interrupt {
439
- intx_interrupt. set_disabled ( command. contains ( cfg_space :: Command :: INTX_DISABLE ) )
452
+ intx_interrupt. set_disabled ( command. intx_disable ( ) )
440
453
}
441
454
}
442
455
443
456
fn update_mmio_enabled ( & mut self , command : cfg_space:: Command ) {
444
- if command. contains ( cfg_space :: Command :: MMIO_ENABLED ) {
457
+ if command. mmio_enabled ( ) {
445
458
self . active_bars = BarMappings :: parse ( & self . state . base_addresses , & self . bar_masks ) ;
446
459
for ( bar, mapping) in self . mapped_memory . iter_mut ( ) . enumerate ( ) {
447
460
if let Some ( mapping) = mapping {
@@ -478,30 +491,19 @@ impl ConfigSpaceType0Emulator {
478
491
479
492
match HeaderType00 ( offset) {
480
493
HeaderType00 :: STATUS_COMMAND => {
481
- let command = match cfg_space:: Command :: from_bits ( val as u16 ) {
482
- Some ( command) => command,
483
- None => {
484
- tracelimit:: warn_ratelimited!( offset, val, "setting invalid command bits" ) ;
485
- // still do our best
486
- cfg_space:: Command :: from_bits_truncate ( val as u16 )
487
- }
494
+ let mut command = cfg_space:: Command :: from_bits ( val as u16 ) ;
495
+ if command. into_bits ( ) & !SUPPORTED_COMMAND_BITS != 0 {
496
+ tracelimit:: warn_ratelimited!( offset, val, "setting invalid command bits" ) ;
497
+ // still do our best
498
+ command =
499
+ cfg_space:: Command :: from_bits ( command. into_bits ( ) & SUPPORTED_COMMAND_BITS ) ;
488
500
} ;
489
501
490
- if self
491
- . state
492
- . command
493
- . contains ( cfg_space:: Command :: INTX_DISABLE )
494
- != command. contains ( cfg_space:: Command :: INTX_DISABLE )
495
- {
502
+ if self . state . command . intx_disable ( ) != command. intx_disable ( ) {
496
503
self . update_intx_disable ( command)
497
504
}
498
505
499
- if self
500
- . state
501
- . command
502
- . contains ( cfg_space:: Command :: MMIO_ENABLED )
503
- != command. contains ( cfg_space:: Command :: MMIO_ENABLED )
504
- {
506
+ if self . state . command . mmio_enabled ( ) != command. mmio_enabled ( ) {
505
507
self . update_mmio_enabled ( command)
506
508
}
507
509
@@ -518,15 +520,13 @@ impl ConfigSpaceType0Emulator {
518
520
| HeaderType00 :: BAR3
519
521
| HeaderType00 :: BAR4
520
522
| HeaderType00 :: BAR5 => {
521
- if !self
522
- . state
523
- . command
524
- . contains ( cfg_space:: Command :: MMIO_ENABLED )
525
- {
523
+ if !self . state . command . mmio_enabled ( ) {
526
524
let bar_index = ( offset - HeaderType00 :: BAR0 . 0 ) as usize / 4 ;
527
525
let mut bar_value = val & self . bar_masks [ bar_index] ;
528
526
if bar_index & 1 == 0 && self . bar_masks [ bar_index] != 0 {
529
- bar_value |= cfg_space:: BarEncodingBits :: TYPE_64_BIT . bits ( ) ;
527
+ bar_value = cfg_space:: BarEncodingBits :: from_bits ( bar_value)
528
+ . with_type_64_bit ( true )
529
+ . into_bits ( ) ;
530
530
}
531
531
self . state . base_addresses [ bar_index] = bar_value;
532
532
}
@@ -623,7 +623,7 @@ mod save_restore {
623
623
} = self . state ;
624
624
625
625
let saved_state = state:: SavedState {
626
- command : command. bits ( ) ,
626
+ command : command. into_bits ( ) ,
627
627
base_addresses,
628
628
interrupt_line,
629
629
latency_timer,
@@ -650,16 +650,18 @@ mod save_restore {
650
650
} = state;
651
651
652
652
self . state = ConfigSpaceType0EmulatorState {
653
- command : cfg_space:: Command :: from_bits ( command) . ok_or (
654
- RestoreError :: InvalidSavedState (
655
- ConfigSpaceRestoreError :: InvalidConfigBits . into ( ) ,
656
- ) ,
657
- ) ?,
653
+ command : cfg_space:: Command :: from_bits ( command) ,
658
654
base_addresses,
659
655
interrupt_line,
660
656
latency_timer,
661
657
} ;
662
658
659
+ if command & !SUPPORTED_COMMAND_BITS != 0 {
660
+ return Err ( RestoreError :: InvalidSavedState (
661
+ ConfigSpaceRestoreError :: InvalidConfigBits . into ( ) ,
662
+ ) ) ;
663
+ }
664
+
663
665
self . sync_command_register ( self . state . command ) ;
664
666
for ( id, entry) in capabilities {
665
667
tracing:: debug!( save_id = id. as_str( ) , "restoring pci capability" ) ;
0 commit comments