Skip to content

Commit 4f3712e

Browse files
nithind1988jerinjacobk
authored andcommitted
virtio: fix feature set logic
Fix feature select and feature set logic to use previously selected feature select to be in sync. Also add a device type specific feature validate cb that will validate and dump features in debug mode in more readable format. Change-Id: I2685a01176d71d02e5d941fd061a224cf43e5d1b Signed-off-by: Nithin Dabilpuram <ndabilpuram@marvell.com> Reviewed-on: https://sj1git1.cavium.com/c/IP/SW/dataplane/dpu-offload/+/144184 Tested-by: sa_ip-toolkits-Jenkins <sa_ip-toolkits-jenkins@marvell.com> Reviewed-by: Srujana Challa <schalla@marvell.com> Reviewed-by: Jerin Jacob <jerinj@marvell.com>
1 parent b011e75 commit 4f3712e

File tree

3 files changed

+163
-16
lines changed

3 files changed

+163
-16
lines changed

lib/virtio/virtio_dev.c

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
#define VIRTIO_QUEUE_SELECT_DELAY 3
1616
#define VIRTIO_DEVICE_STATUS_DELAY 5
1717

18-
#define VIRTIO_INVALID_QUEUE_INDEX 0xFFFF
18+
#define VIRTIO_INVALID_QUEUE_INDEX 0xFFFF
19+
#define VIRTIO_INVALID_FEATURE_SELECT 0xFFFF
1920

2021
struct virtio_ctrl_queue {
2122
uintptr_t desc_base;
@@ -40,6 +41,12 @@ virtio_process_device_feature_select(struct virtio_dev *dev, uintptr_t shadow,
4041
volatile struct virtio_pci_common_cfg *common_cfg = dev->common_cfg;
4142
uint32_t feature_select = device_feature_select & 0x7fff;
4243

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+
4350
if (feature_select == 0)
4451
common_cfg->device_feature = (uint32_t)dev->dev_feature_bits & BIT_MASK32;
4552
else if (feature_select == 1)
@@ -75,6 +82,11 @@ virtio_process_driver_feature_select(struct virtio_dev *dev, uintptr_t shadow,
7582
uint32_t prev_feature_select = dev->prev_drv_feature_select;
7683
uint32_t feature_select = driver_feature_select & 0x7fff;
7784

85+
if (driver_feature_select == VIRTIO_INVALID_FEATURE_SELECT) {
86+
shadow_cfg->driver_feature_select = driver_feature_select;
87+
return 0;
88+
}
89+
7890
if (prev_feature_select != 0xffff) {
7991
if (prev_feature_select == 0)
8092
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,
8597
dev->common_cfg->driver_feature);
8698
}
8799

100+
dao_dbg("[dev %u] feature selected: %u", dev->dev_id, feature_select);
88101
/* Store feature select as driver can proceed to write driver feature and again
89102
* change driver feature select before device processing device_feature of
90103
* previous one.
@@ -95,9 +108,10 @@ virtio_process_driver_feature_select(struct virtio_dev *dev, uintptr_t shadow,
95108
else if (feature_select == 1)
96109
dev->common_cfg->driver_feature = dev->drv_feature_bits_hi;
97110

111+
shadow_cfg->driver_feature = dev->common_cfg->driver_feature;
98112
rte_wmb();
113+
99114
shadow_cfg->driver_feature_select = feature_select;
100-
shadow_cfg->driver_feature = dev->common_cfg->driver_feature;
101115
dev->common_cfg->driver_feature_select = feature_select;
102116
rte_wmb();
103117

@@ -110,7 +124,7 @@ static int
110124
virtio_process_driver_feature(struct virtio_dev *dev, uintptr_t shadow, uint32_t driver_feature)
111125
{
112126
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;
114128

115129
if (feature_select == 0)
116130
dev->drv_feature_bits_lo = driver_feature;
@@ -146,8 +160,8 @@ virtio_config_populate(struct virtio_dev *dev)
146160

147161
/* Populate common config and init notify area with initial wrap count */
148162
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;
151165

152166
/* Reset notification area */
153167
for (i = 0; i < max_virtio_queues; i++) {
@@ -156,7 +170,7 @@ virtio_config_populate(struct virtio_dev *dev)
156170
}
157171

158172
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;
160174

161175
/* Initialize queue config defaults */
162176
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)
389403
static int
390404
virtio_process_device_status(struct virtio_dev *dev, uintptr_t shadow, uint8_t device_status)
391405
{
406+
virtio_feature_validate_cb_t feature_validate_cb = dev_cbs[dev->dev_type].feature_validate;
392407
struct virtio_pci_common_cfg *shadow_cfg = (struct virtio_pci_common_cfg *)shadow;
393408
virtio_dev_status_cb_t dev_status_cb = dev_cbs[dev->dev_type].dev_status;
394409
uint8_t status = device_status & 0x7f;
410+
uint64_t feature_bits;
395411

396412
dao_dbg("[dev %u] device_status: 0x%x", dev->dev_id, device_status);
397413

@@ -414,22 +430,31 @@ virtio_process_device_status(struct virtio_dev *dev, uintptr_t shadow, uint8_t d
414430
}
415431

416432
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;
417434
dao_info("[dev %u] %s", dev->dev_id,
418435
dao_virtio_dev_status_to_str(VIRTIO_DEV_FEATURES_OK));
419436

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;
422447
dev->features_ok = 1;
423448
shadow_cfg->device_status |= VIRTIO_DEV_FEATURES_OK;
424-
dao_info("[dev %u] Feature bits negotiated : %lx", dev->dev_id, dev->feature_bits);
449+
425450
if ((dev->feature_bits & RTE_BIT64(VIRTIO_F_ORDER_PLATFORM)) == 0) {
426451
dao_warn("[dev %u] !!! VIRTIO_F_ORDER_PLATFORM not negotiated !!!",
427452
dev->dev_id);
428453
dao_warn("[dev %u] !!! Can lead to out-of-sync descriptor data !!!",
429454
dev->dev_id);
430455
}
431456
}
432-
457+
next:
433458
if (status & VIRTIO_DEV_DRIVER_OK && !dev->driver_ok) {
434459
/* Return to go through other changes and come back as we might not seeing
435460
* writes in order.
@@ -798,25 +823,25 @@ dao_virtio_common_cfg_cb(void *ctx, uintptr_t shadow, uint32_t offset, uint64_t
798823
up_cfg.w0 = val;
799824
shd_cfg.w0 = shadow_val;
800825
update_shadow = false;
826+
if (up_cfg.device_feature != shd_cfg.device_feature)
827+
virtio_process_device_feature(dev, up_cfg.device_feature);
828+
801829
if (up_cfg.device_feature_select != shd_cfg.device_feature_select)
802830
virtio_process_device_feature_select(dev, shadow,
803831
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);
807832
break;
808833

809834
case 1:
810835
/* driver_feature_select, driver_feature */
811836
up_cfg.w1 = val;
812837
shd_cfg.w1 = shadow_val;
813838
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+
814842
if (up_cfg.driver_feature_select != shd_cfg.driver_feature_select)
815843
virtio_process_driver_feature_select(dev, shadow,
816844
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);
820845
break;
821846

822847
case 2:

lib/virtio/virtio_dev_priv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,14 @@ typedef void (*virtio_cq_cmd_process_cb_t)(struct virtio_dev *dev, struct rte_dm
5757
typedef int (*virtio_dev_status_cb_t)(struct virtio_dev *dev, uint8_t status);
5858
typedef uint16_t (*virtio_cq_id_get_cb_t)(struct virtio_dev *dev, uint64_t feature_bits);
5959
typedef int (*virtio_queue_enable_cb_t)(struct virtio_dev *dev, uint16_t queue_id);
60+
typedef int (*virtio_feature_validate_cb_t)(struct virtio_dev *dev, uint64_t feature_bits);
6061

6162
struct virtio_dev_cbs {
6263
virtio_cq_cmd_process_cb_t cq_cmd_process;
6364
virtio_dev_status_cb_t dev_status;
6465
virtio_cq_id_get_cb_t cq_id_get;
6566
virtio_queue_enable_cb_t queue_enable;
67+
virtio_feature_validate_cb_t feature_validate;
6668
};
6769

6870
struct virtio_pci_cap {

lib/virtio_net/virtio_netdev.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,125 @@ dao_net_desc_manage_fn_t dao_net_desc_manage_fns[VIRTIO_NET_DESC_MANAGE_LAST <<
2020
struct dao_virtio_netdev_cbs user_cbs;
2121
int virtio_netdev_clear_queue_info(struct virtio_netdev *netdev);
2222

23+
static int
24+
virtio_netdev_feature_validate(struct virtio_dev *dev, uint64_t feature_bits)
25+
{
26+
uint16_t dev_id = dev->dev_id;
27+
int i;
28+
29+
if ((feature_bits | dev->dev_feature_bits) != dev->dev_feature_bits) {
30+
dao_err("[dev %u] Invalid feature bits negotiated 0x%" PRIx64 "(dev %" PRIx64 ")",
31+
dev_id, feature_bits, dev->dev_feature_bits);
32+
return -EINVAL;
33+
}
34+
35+
/* Dump features enabled for debug purpose */
36+
dao_dbg("[dev %u] Features enabled:", dev_id);
37+
for (i = 0; i < 64; i++) {
38+
if (!(feature_bits & DAO_BIT(i)))
39+
continue;
40+
switch (i) {
41+
case VIRTIO_NET_F_CSUM:
42+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_CSUM");
43+
break;
44+
case VIRTIO_NET_F_GUEST_CSUM:
45+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_GUEST_CSUM");
46+
break;
47+
case VIRTIO_NET_F_MTU:
48+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_MTU");
49+
break;
50+
case VIRTIO_NET_F_MAC:
51+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_MAC");
52+
break;
53+
case VIRTIO_NET_F_GUEST_TSO4:
54+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_GUEST_TSO4");
55+
break;
56+
case VIRTIO_NET_F_GUEST_TSO6:
57+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_GUEST_TSO6");
58+
break;
59+
case VIRTIO_NET_F_GUEST_ECN:
60+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_GUEST_ECN");
61+
break;
62+
case VIRTIO_NET_F_GUEST_UFO:
63+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_GUEST_UFO");
64+
break;
65+
case VIRTIO_NET_F_HOST_TSO4:
66+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_HOST_TSO4");
67+
break;
68+
case VIRTIO_NET_F_HOST_TSO6:
69+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_HOST_TSO6");
70+
break;
71+
case VIRTIO_NET_F_HOST_ECN:
72+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_HOST_ECN");
73+
break;
74+
case VIRTIO_NET_F_HOST_UFO:
75+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_HOST_UFO");
76+
break;
77+
case VIRTIO_NET_F_MRG_RXBUF:
78+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_MRG_RXBUF");
79+
break;
80+
case VIRTIO_NET_F_STATUS:
81+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_STATUS");
82+
break;
83+
case VIRTIO_NET_F_CTRL_VQ:
84+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_CTRL_VQ");
85+
break;
86+
case VIRTIO_NET_F_CTRL_RX:
87+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_CTRL_RX");
88+
break;
89+
case VIRTIO_NET_F_CTRL_VLAN:
90+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_CTRL_VLAN");
91+
break;
92+
case VIRTIO_NET_F_CTRL_RX_EXTRA:
93+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_CTRL_RX_EXTRA");
94+
break;
95+
case VIRTIO_NET_F_GUEST_ANNOUNCE:
96+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_GUEST_ANNOUNCE");
97+
break;
98+
case VIRTIO_NET_F_MQ:
99+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_MQ");
100+
break;
101+
case VIRTIO_NET_F_CTRL_MAC_ADDR:
102+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_CTRL_MAC_ADDR");
103+
break;
104+
case VIRTIO_NET_F_HASH_REPORT:
105+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_HASH_REPORT");
106+
break;
107+
case VIRTIO_NET_F_GUEST_HDRLEN:
108+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_GUEST_HDRLEN");
109+
break;
110+
case VIRTIO_NET_F_RSS:
111+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_RSS");
112+
break;
113+
case VIRTIO_NET_F_SPEED_DUPLEX:
114+
dao_dbg("[dev %u] +%s", dev_id, "VIRTIO_NET_F_SPEED_DUPLEX");
115+
break;
116+
case VIRTIO_F_VERSION_1:
117+
dao_dbg("[dev %u] +%s", dev->dev_id, "VIRTIO_F_VERSION_1");
118+
break;
119+
case VIRTIO_F_IOMMU_PLATFORM:
120+
dao_dbg("[dev %u] +%s", dev->dev_id, "VIRTIO_F_IOMMU_PLATFORM");
121+
break;
122+
case VIRTIO_F_RING_PACKED:
123+
dao_dbg("[dev %u] +%s", dev->dev_id, "VIRTIO_F_RING_PACKED");
124+
break;
125+
case VIRTIO_F_IN_ORDER:
126+
dao_dbg("[dev %u] +%s", dev->dev_id, "VIRTIO_F_IN_ORDER");
127+
break;
128+
case VIRTIO_F_ORDER_PLATFORM:
129+
dao_dbg("[dev %u] +%s", dev->dev_id, "VIRTIO_F_ORDER_PLATFORM");
130+
break;
131+
case VIRTIO_F_NOTIFICATION_DATA:
132+
dao_dbg("[dev %u] +%s", dev->dev_id, "VIRTIO_F_NOTIFICATION_DATA");
133+
break;
134+
default:
135+
dao_err("[dev %u] Unknown feature bit %d", dev_id, i);
136+
break;
137+
};
138+
}
139+
return 0;
140+
}
141+
23142
static void
24143
virtio_hash_types_to_hash_report(struct virtio_netdev *netdev, uint64_t virtio_hash_types)
25144
{
@@ -762,6 +881,7 @@ dao_virtio_netdev_init(uint16_t devid, struct dao_virtio_netdev_conf *conf)
762881
dev_cbs[VIRTIO_DEV_TYPE_NET].cq_cmd_process = virtio_netdev_cq_cmd_process;
763882
dev_cbs[VIRTIO_DEV_TYPE_NET].cq_id_get = virtio_netdev_cq_id_get;
764883
dev_cbs[VIRTIO_DEV_TYPE_NET].queue_enable = virtio_netdev_queue_enable;
884+
dev_cbs[VIRTIO_DEV_TYPE_NET].feature_validate = virtio_netdev_feature_validate;
765885
return 0;
766886
}
767887

0 commit comments

Comments
 (0)