15
15
#define VIRTIO_QUEUE_SELECT_DELAY 3
16
16
#define VIRTIO_DEVICE_STATUS_DELAY 5
17
17
18
- #define VIRTIO_INVALID_QUEUE_INDEX 0xFFFF
18
+ #define VIRTIO_INVALID_QUEUE_INDEX 0xFFFF
19
+ #define VIRTIO_INVALID_FEATURE_SELECT 0xFFFF
19
20
20
21
struct virtio_ctrl_queue {
21
22
uintptr_t desc_base ;
@@ -40,6 +41,12 @@ virtio_process_device_feature_select(struct virtio_dev *dev, uintptr_t shadow,
40
41
volatile struct virtio_pci_common_cfg * common_cfg = dev -> common_cfg ;
41
42
uint32_t feature_select = device_feature_select & 0x7fff ;
42
43
44
+ /* Skip if it is during init */
45
+ if (device_feature_select == VIRTIO_INVALID_FEATURE_SELECT ) {
46
+ shadow_cfg -> device_feature_select = device_feature_select ;
47
+ return 0 ;
48
+ }
49
+
43
50
if (feature_select == 0 )
44
51
common_cfg -> device_feature = (uint32_t )dev -> dev_feature_bits & BIT_MASK32 ;
45
52
else if (feature_select == 1 )
@@ -75,6 +82,11 @@ virtio_process_driver_feature_select(struct virtio_dev *dev, uintptr_t shadow,
75
82
uint32_t prev_feature_select = dev -> prev_drv_feature_select ;
76
83
uint32_t feature_select = driver_feature_select & 0x7fff ;
77
84
85
+ if (driver_feature_select == VIRTIO_INVALID_FEATURE_SELECT ) {
86
+ shadow_cfg -> driver_feature_select = driver_feature_select ;
87
+ return 0 ;
88
+ }
89
+
78
90
if (prev_feature_select != 0xffff ) {
79
91
if (prev_feature_select == 0 )
80
92
dev -> drv_feature_bits_lo = dev -> common_cfg -> driver_feature ;
@@ -85,6 +97,7 @@ virtio_process_driver_feature_select(struct virtio_dev *dev, uintptr_t shadow,
85
97
dev -> common_cfg -> driver_feature );
86
98
}
87
99
100
+ dao_dbg ("[dev %u] feature selected: %u" , dev -> dev_id , feature_select );
88
101
/* Store feature select as driver can proceed to write driver feature and again
89
102
* change driver feature select before device processing device_feature of
90
103
* previous one.
@@ -95,9 +108,10 @@ virtio_process_driver_feature_select(struct virtio_dev *dev, uintptr_t shadow,
95
108
else if (feature_select == 1 )
96
109
dev -> common_cfg -> driver_feature = dev -> drv_feature_bits_hi ;
97
110
111
+ shadow_cfg -> driver_feature = dev -> common_cfg -> driver_feature ;
98
112
rte_wmb ();
113
+
99
114
shadow_cfg -> driver_feature_select = feature_select ;
100
- shadow_cfg -> driver_feature = dev -> common_cfg -> driver_feature ;
101
115
dev -> common_cfg -> driver_feature_select = feature_select ;
102
116
rte_wmb ();
103
117
@@ -110,7 +124,7 @@ static int
110
124
virtio_process_driver_feature (struct virtio_dev * dev , uintptr_t shadow , uint32_t driver_feature )
111
125
{
112
126
struct virtio_pci_common_cfg * shadow_cfg = (struct virtio_pci_common_cfg * )shadow ;
113
- uint32_t feature_select = dev -> common_cfg -> driver_feature_select ;
127
+ uint32_t feature_select = dev -> prev_drv_feature_select ;
114
128
115
129
if (feature_select == 0 )
116
130
dev -> drv_feature_bits_lo = driver_feature ;
@@ -146,8 +160,8 @@ virtio_config_populate(struct virtio_dev *dev)
146
160
147
161
/* Populate common config and init notify area with initial wrap count */
148
162
common_cfg -> num_queues = max_virtio_queues ;
149
- common_cfg -> device_feature_select = -1 ;
150
- common_cfg -> driver_feature_select = -1 ;
163
+ common_cfg -> device_feature_select = VIRTIO_INVALID_FEATURE_SELECT ;
164
+ common_cfg -> driver_feature_select = VIRTIO_INVALID_FEATURE_SELECT ;
151
165
152
166
/* Reset notification area */
153
167
for (i = 0 ; i < max_virtio_queues ; i ++ ) {
@@ -156,7 +170,7 @@ virtio_config_populate(struct virtio_dev *dev)
156
170
}
157
171
158
172
dev -> prev_queue_select = VIRTIO_INVALID_QUEUE_INDEX ;
159
- dev -> prev_drv_feature_select = 0xffff ;
173
+ dev -> prev_drv_feature_select = VIRTIO_INVALID_FEATURE_SELECT ;
160
174
161
175
/* Initialize queue config defaults */
162
176
memset (dev -> queue_conf , 0 , max_virtio_queues * sizeof (struct virtio_queue_conf ));
@@ -389,9 +403,11 @@ virtio_setup_cq_info(struct virtio_dev *dev)
389
403
static int
390
404
virtio_process_device_status (struct virtio_dev * dev , uintptr_t shadow , uint8_t device_status )
391
405
{
406
+ virtio_feature_validate_cb_t feature_validate_cb = dev_cbs [dev -> dev_type ].feature_validate ;
392
407
struct virtio_pci_common_cfg * shadow_cfg = (struct virtio_pci_common_cfg * )shadow ;
393
408
virtio_dev_status_cb_t dev_status_cb = dev_cbs [dev -> dev_type ].dev_status ;
394
409
uint8_t status = device_status & 0x7f ;
410
+ uint64_t feature_bits ;
395
411
396
412
dao_dbg ("[dev %u] device_status: 0x%x" , dev -> dev_id , device_status );
397
413
@@ -414,22 +430,31 @@ virtio_process_device_status(struct virtio_dev *dev, uintptr_t shadow, uint8_t d
414
430
}
415
431
416
432
if (status & VIRTIO_DEV_FEATURES_OK && !dev -> features_ok ) {
433
+ feature_bits = dev -> drv_feature_bits_lo | (uint64_t )dev -> drv_feature_bits_hi << 32 ;
417
434
dao_info ("[dev %u] %s" , dev -> dev_id ,
418
435
dao_virtio_dev_status_to_str (VIRTIO_DEV_FEATURES_OK ));
419
436
420
- dev -> feature_bits = dev -> drv_feature_bits_lo | (uint64_t )dev -> drv_feature_bits_hi
421
- << 32 ;
437
+ dao_info ("[dev %u] Feature bits negotiated : %lx" , dev -> dev_id , feature_bits );
438
+ if (feature_validate_cb && feature_validate_cb (dev , feature_bits )) {
439
+ /* Feature validation failed */
440
+ dao_err ("[dev %u] Feature validation failed" , dev -> dev_id );
441
+ dev -> common_cfg -> device_status &= ~VIRTIO_DEV_FEATURES_OK ;
442
+ shadow_cfg -> device_status &= ~VIRTIO_DEV_FEATURES_OK ;
443
+ goto next ;
444
+ }
445
+
446
+ dev -> feature_bits = feature_bits ;
422
447
dev -> features_ok = 1 ;
423
448
shadow_cfg -> device_status |= VIRTIO_DEV_FEATURES_OK ;
424
- dao_info ( "[dev %u] Feature bits negotiated : %lx" , dev -> dev_id , dev -> feature_bits );
449
+
425
450
if ((dev -> feature_bits & RTE_BIT64 (VIRTIO_F_ORDER_PLATFORM )) == 0 ) {
426
451
dao_warn ("[dev %u] !!! VIRTIO_F_ORDER_PLATFORM not negotiated !!!" ,
427
452
dev -> dev_id );
428
453
dao_warn ("[dev %u] !!! Can lead to out-of-sync descriptor data !!!" ,
429
454
dev -> dev_id );
430
455
}
431
456
}
432
-
457
+ next :
433
458
if (status & VIRTIO_DEV_DRIVER_OK && !dev -> driver_ok ) {
434
459
/* Return to go through other changes and come back as we might not seeing
435
460
* writes in order.
@@ -798,25 +823,25 @@ dao_virtio_common_cfg_cb(void *ctx, uintptr_t shadow, uint32_t offset, uint64_t
798
823
up_cfg .w0 = val ;
799
824
shd_cfg .w0 = shadow_val ;
800
825
update_shadow = false;
826
+ if (up_cfg .device_feature != shd_cfg .device_feature )
827
+ virtio_process_device_feature (dev , up_cfg .device_feature );
828
+
801
829
if (up_cfg .device_feature_select != shd_cfg .device_feature_select )
802
830
virtio_process_device_feature_select (dev , shadow ,
803
831
up_cfg .device_feature_select );
804
-
805
- if (up_cfg .device_feature != shd_cfg .device_feature )
806
- virtio_process_device_feature (dev , up_cfg .device_feature );
807
832
break ;
808
833
809
834
case 1 :
810
835
/* driver_feature_select, driver_feature */
811
836
up_cfg .w1 = val ;
812
837
shd_cfg .w1 = shadow_val ;
813
838
update_shadow = false;
839
+ if (up_cfg .driver_feature != shd_cfg .driver_feature )
840
+ virtio_process_driver_feature (dev , shadow , up_cfg .driver_feature );
841
+
814
842
if (up_cfg .driver_feature_select != shd_cfg .driver_feature_select )
815
843
virtio_process_driver_feature_select (dev , shadow ,
816
844
up_cfg .driver_feature_select );
817
-
818
- if (up_cfg .driver_feature != shd_cfg .driver_feature )
819
- virtio_process_driver_feature (dev , shadow , up_cfg .driver_feature );
820
845
break ;
821
846
822
847
case 2 :
0 commit comments