FD.io VPP  v21.01.1
Vector Packet Processing
virtio_pci_modern.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <fcntl.h>
17 #include <sys/ioctl.h>
18 
19 #include <vppinfra/types.h>
20 #include <vlib/vlib.h>
21 #include <vlib/pci/pci.h>
22 #include <vnet/ethernet/ethernet.h>
23 #include <vnet/ip/ip4_packet.h>
24 #include <vnet/ip/ip6_packet.h>
28 
29 
30 static u64
32 {
33  u64 features_lo, features_hi;
34  virtio_pci_reg_write_u32 (vif, VIRTIO_DEVICE_FEATURE_SELECT_OFFSET (vif),
36  features_lo =
37  virtio_pci_reg_read_u32 (vif, VIRTIO_DEVICE_FEATURE_OFFSET (vif));
38  virtio_pci_reg_write_u32 (vif, VIRTIO_DEVICE_FEATURE_SELECT_OFFSET (vif),
40  features_hi =
41  virtio_pci_reg_read_u32 (vif, VIRTIO_DEVICE_FEATURE_OFFSET (vif));
42  u64 features = ((features_hi << 32) | features_lo);
43  return features;
44 }
45 
46 static u64
48 {
49  u64 features_lo, features_hi;
50  virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_SELECT_OFFSET (vif),
52  features_lo =
53  virtio_pci_reg_read_u32 (vif, VIRTIO_DRIVER_FEATURE_OFFSET (vif));
54  virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_SELECT_OFFSET (vif),
56  features_hi =
57  virtio_pci_reg_read_u32 (vif, VIRTIO_DRIVER_FEATURE_OFFSET (vif));
58 
59  vif->features = ((features_hi << 32) | features_lo);
60  return vif->features;
61 }
62 
63 static void
65  u64 features)
66 {
67  u32 features_lo = (u32) features, features_hi = (u32) (features >> 32);
68  virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_SELECT_OFFSET (vif),
70  virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_OFFSET (vif),
71  features_lo);
72  virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_SELECT_OFFSET (vif),
74  virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_OFFSET (vif),
75  features_hi);
76 
77  if (features != virtio_pci_modern_get_driver_features (vm, vif))
78  {
79  clib_warning ("modern set guest features failed!");
80  }
81 }
82 
83 static u16
85 {
86  u16 msix_config;
87  msix_config =
88  virtio_pci_reg_read_u16 (vif, VIRTIO_MSIX_CONFIG_VECTOR_OFFSET (vif));
89  return msix_config;
90 }
91 
92 static u16
94  u16 msix_config)
95 {
96  virtio_pci_reg_write_u16 (vif, VIRTIO_MSIX_CONFIG_VECTOR_OFFSET (vif),
97  msix_config);
99 }
100 
101 static u16
103 {
104  u16 num_queues = 0;
105  num_queues = virtio_pci_reg_read_u16 (vif, VIRTIO_NUM_QUEUES_OFFSET (vif));
106  return num_queues;
107 }
108 
109 static u8
111 {
112  u8 status = 0;
113  status = virtio_pci_reg_read_u8 (vif, VIRTIO_DEVICE_STATUS_OFFSET (vif));
114  return status;
115 }
116 
117 static void
119 {
120  if (status != VIRTIO_CONFIG_STATUS_RESET)
121  status |= virtio_pci_modern_get_status (vm, vif);
122  virtio_pci_reg_write_u8 (vif, VIRTIO_DEVICE_STATUS_OFFSET (vif), status);
123 }
124 
125 static u8
127 {
128  virtio_pci_modern_set_status (vm, vif, VIRTIO_CONFIG_STATUS_RESET);
129  return virtio_pci_modern_get_status (vm, vif);
130 }
131 
132 static u8
134 {
135  u8 config_generation = 0;
136  config_generation =
137  virtio_pci_reg_read_u8 (vif, VIRTIO_CONFIG_GENERATION_OFFSET (vif));
138  return config_generation;
139 }
140 
141 static void
143 {
144  virtio_pci_reg_write_u16 (vif, VIRTIO_QUEUE_SELECT_OFFSET (vif),
145  queue_select);
146 }
147 
148 static u16
150  u16 queue_id)
151 {
152  u16 queue_size = 0;
153  virtio_pci_modern_set_queue_select (vif, queue_id);
154  queue_size = virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_SIZE_OFFSET (vif));
155  return queue_size;
156 }
157 
158 static void
160  u16 queue_id, u16 queue_size)
161 {
162  if (!is_pow2 (queue_size))
163  {
164  return;
165  }
166 
167  if (virtio_pci_modern_get_queue_size (vm, vif, queue_id) > queue_size)
168  virtio_pci_reg_write_u16 (vif, VIRTIO_QUEUE_SIZE_OFFSET (vif),
169  queue_size);
170 }
171 
172 static u16
174 {
175  u16 queue_msix_vector = 0;
176  queue_msix_vector =
177  virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_MSIX_VECTOR_OFFSET (vif));
178  return queue_msix_vector;
179 }
180 
181 static u16
183  u16 queue_msix_vector, u16 queue_id)
184 {
185  virtio_pci_modern_set_queue_select (vif, queue_id);
186  virtio_pci_reg_write_u16 (vif, VIRTIO_QUEUE_MSIX_VECTOR_OFFSET (vif),
187  queue_msix_vector);
189 }
190 
191 static u16
193 {
194  u16 queue_enable = 0;
195  virtio_pci_modern_set_queue_select (vif, queue_id);
196  queue_enable =
197  virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_ENABLE_OFFSET (vif));
198  return queue_enable;
199 }
200 
201 static void
203  u16 queue_enable)
204 {
205  virtio_pci_modern_set_queue_select (vif, queue_id);
206  virtio_pci_reg_write_u16 (vif, VIRTIO_QUEUE_ENABLE_OFFSET (vif),
207  queue_enable);
208 }
209 
210 static u16
212  u16 queue_id)
213 {
214  u16 queue_notify_off = 0;
215  virtio_pci_modern_set_queue_select (vif, queue_id);
216  queue_notify_off =
217  virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_NOTIFY_OFF_OFFSET (vif));
218  return queue_notify_off;
219 }
220 
221 static u64
223 {
224  u64 queue_desc = 0;
225  queue_desc = virtio_pci_reg_read_u64 (vif, VIRTIO_QUEUE_DESC_OFFSET (vif));
226  return queue_desc;
227 }
228 
229 static void
231 {
232  virtio_pci_reg_write_u64 (vif, VIRTIO_QUEUE_DESC_OFFSET (vif), queue_desc);
233 }
234 
235 static u64
237 {
238  u64 queue_driver = 0;
239  queue_driver =
240  virtio_pci_reg_read_u64 (vif, VIRTIO_QUEUE_DRIVER_OFFSET (vif));
241  return queue_driver;
242 }
243 
244 static void
246 {
247  virtio_pci_reg_write_u64 (vif, VIRTIO_QUEUE_DRIVER_OFFSET (vif),
248  queue_driver);
249 }
250 
251 static u64
253 {
254  u64 queue_device = 0;
255  queue_device =
256  virtio_pci_reg_read_u64 (vif, VIRTIO_QUEUE_DEVICE_OFFSET (vif));
257  return queue_device;
258 }
259 
260 static void
262 {
263  virtio_pci_reg_write_u64 (vif, VIRTIO_QUEUE_DEVICE_OFFSET (vif),
264  queue_device);
265 }
266 
267 static u8
269  u16 queue_id, void *p)
270 {
271  u64 desc, avail, used;
272  u16 queue_size = 0;
273 
274  virtio_pci_modern_set_queue_select (vif, queue_id);
275  queue_size = virtio_pci_modern_get_queue_size (vm, vif, queue_id);
276 
277  if (vif->is_packed)
278  {
279  virtio_vring_t *vring = (virtio_vring_t *) p;
280 
281  desc = vlib_physmem_get_pa (vm, vring->packed_desc);
282  avail = vlib_physmem_get_pa (vm, vring->driver_event);
283  used = vlib_physmem_get_pa (vm, vring->device_event);
284  }
285  else
286  {
287  vring_t vr;
288 
289  vring_init (&vr, queue_size, p, VIRTIO_PCI_VRING_ALIGN);
290 
291  desc = vlib_physmem_get_pa (vm, vr.desc);
292  avail = vlib_physmem_get_pa (vm, vr.avail);
293  used = vlib_physmem_get_pa (vm, vr.used);
294  }
295 
297  if (desc != virtio_pci_modern_get_queue_desc (vif))
298  return 1;
299 
301  if (avail != virtio_pci_modern_get_queue_driver (vif))
302  return 1;
303 
305  if (used != virtio_pci_modern_get_queue_device (vif))
306  return 1;
307 
308  virtio_pci_modern_set_queue_enable (vif, queue_id, 1);
309 
310  if (virtio_pci_modern_get_queue_enable (vif, queue_id))
311  return 0;
312 
313  return 1;
314 }
315 
316 static void
318  u16 queue_id)
319 {
320  virtio_pci_modern_set_queue_select (vif, queue_id);
321  virtio_pci_modern_set_queue_enable (vif, queue_id, 0);
325 }
326 
327 static void
329 {
330  vif->mac_addr32 = virtio_pci_reg_read_u32 (vif, VIRTIO_MAC_OFFSET (vif));
331  vif->mac_addr16 =
332  virtio_pci_reg_read_u16 (vif, VIRTIO_MAC_OFFSET (vif) + 4);
333 }
334 
335 static void
337 {
338  virtio_pci_reg_write_u32 (vif, VIRTIO_MAC_OFFSET (vif), vif->mac_addr32);
339  virtio_pci_reg_write_u16 (vif, VIRTIO_MAC_OFFSET (vif) + 4,
340  vif->mac_addr16);
341 }
342 
343 static u16
345 {
346  u16 status = 0;
347  status = virtio_pci_reg_read_u16 (vif, VIRTIO_STATUS_OFFSET (vif));
348  return status;
349 }
350 
351 static u16
353  virtio_if_t * vif)
354 {
355  u16 max_virtqueue_pairs = 0;
356  max_virtqueue_pairs =
357  virtio_pci_reg_read_u16 (vif, VIRTIO_MAX_VIRTQUEUE_PAIRS_OFFSET (vif));
358  u16 supported_queues = virtio_pci_modern_get_num_queues (vif);
359  virtio_log_debug (vif, "max-virtqueue-pairs %u, supported-queues %u",
360  max_virtqueue_pairs, supported_queues);
361  return max_virtqueue_pairs;
362 }
363 
364 static u16
366 {
367  u16 mtu = 0;
368  mtu = virtio_pci_reg_read_u16 (vif, VIRTIO_MTU_OFFSET (vif));
369  return mtu;
370 }
371 
372 static void
374  int len, u32 addr)
375 {
376  u8 config_count;
377  do
378  {
379  config_count = virtio_pci_modern_get_config_generation (vif);
381  u16 status = virtio_pci_modern_get_device_status (vm, vif);
382  u16 max_queue_pairs =
384  u16 mtu = virtio_pci_modern_get_device_mtu (vm, vif);
385  virtio_log_debug (vif, "status %u, max_queue_pairs %u, mtu %u", status,
386  max_queue_pairs, mtu);
387  }
388  while (config_count != virtio_pci_modern_get_config_generation (vif));
389 }
390 
391 static void
393  void *src, int len, u32 addr)
394 {
395  // do nothing
396 }
397 
398 static u8
400 {
401  return virtio_pci_reg_read_u8 (vif, VIRTIO_ISR_OFFSET (vif));
402 }
403 
404 inline void
406  u16 queue_id, u16 queue_notify_off)
407 {
408  virtio_pci_reg_write_u16 (vif,
410  queue_notify_off, queue_id);
411 }
412 
413 static void
415  virtio_if_t * vif)
416 {
417  // do nothing for now
418 }
419 
421  .read_config = virtio_pci_modern_read_config,
422  .write_config = virtio_pci_modern_write_config,
423  .get_device_features = virtio_pci_modern_get_device_features,
424  .get_driver_features = virtio_pci_modern_get_driver_features,
425  .set_driver_features = virtio_pci_modern_set_driver_features,
426  .get_status = virtio_pci_modern_get_status,
427  .set_status = virtio_pci_modern_set_status,
428  .device_reset = virtio_pci_modern_reset,
429  .get_isr = virtio_pci_modern_get_isr,
430  .get_queue_size = virtio_pci_modern_get_queue_size,
431  .set_queue_size = virtio_pci_modern_set_queue_size,
432  .setup_queue = virtio_pci_modern_setup_queue,
433  .del_queue = virtio_pci_modern_del_queue,
434  .get_queue_notify_off = virtio_pci_modern_get_queue_notify_off,
435  .notify_queue = virtio_pci_modern_notify_queue,
436  .set_config_irq = virtio_pci_modern_set_msix_config,
440  .get_device_status = virtio_pci_modern_get_device_status,
441  .get_max_queue_pairs = virtio_pci_modern_get_max_virtqueue_pairs,
443  .device_debug_config_space = virtio_pci_modern_device_debug_config_space,
444 };
445 
446 /*
447  * fd.io coding-style-patch-verification: ON
448  *
449  * Local Variables:
450  * eval: (c-set-style "gnu")
451  * End:
452  */
#define VIRTIO_ISR_OFFSET(v)
static u16 virtio_pci_modern_get_max_virtqueue_pairs(vlib_main_t *vm, virtio_if_t *vif)
const virtio_pci_func_t virtio_pci_modern_func
vring_desc_event_t * device_event
Definition: virtio.h:79
static void virtio_pci_modern_read_config(vlib_main_t *vm, virtio_if_t *vif, void *dst, int len, u32 addr)
#define VIRTIO_MAX_VIRTQUEUE_PAIRS_OFFSET(v)
static void virtio_pci_modern_set_queue_enable(virtio_if_t *vif, u16 queue_id, u16 queue_enable)
vring_used_t * used
Definition: virtio_std.h:177
static u64 virtio_pci_modern_get_queue_desc(virtio_if_t *vif)
void virtio_pci_modern_notify_queue(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id, u16 queue_notify_off)
unsigned long u64
Definition: types.h:89
#define VIRTIO_QUEUE_DRIVER_OFFSET(v)
#define VIRTIO_QUEUE_DEVICE_OFFSET(v)
vl_api_address_t src
Definition: gre.api:54
#define VIRTIO_NUM_QUEUES_OFFSET(v)
vlib_main_t * vm
Definition: in2out_ed.c:1580
#define VIRTIO_QUEUE_MSIX_VECTOR_OFFSET(v)
vring_avail_t * avail
Definition: virtio_std.h:176
vhost_vring_addr_t addr
Definition: vhost_user.h:111
unsigned char u8
Definition: types.h:56
static u8 virtio_pci_modern_reset(vlib_main_t *vm, virtio_if_t *vif)
static void virtio_pci_modern_set_driver_features(vlib_main_t *vm, virtio_if_t *vif, u64 features)
u64 features
Definition: virtio.h:130
static u16 virtio_pci_modern_get_num_queues(virtio_if_t *vif)
#define VIRTIO_DEVICE_STATUS_OFFSET(v)
#define VIRTIO_QUEUE_NOTIFY_OFF_OFFSET(v)
static u8 virtio_pci_modern_get_status(vlib_main_t *vm, virtio_if_t *vif)
#define VIRTIO_DRIVER_FEATURE_OFFSET(v)
#define VIRTIO_STATUS_OFFSET(v)
unsigned int u32
Definition: types.h:88
#define VIRTIO_FEATURE_SELECT_LO
static u16 virtio_pci_modern_get_queue_enable(virtio_if_t *vif, u16 queue_id)
static u16 virtio_pci_modern_get_queue_size(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id)
vring_desc_event_t * driver_event
Definition: virtio.h:78
unsigned short u16
Definition: types.h:57
#define VIRTIO_CONFIG_GENERATION_OFFSET(v)
#define VIRTIO_QUEUE_SELECT_OFFSET(v)
static u16 virtio_pci_modern_set_queue_msix_vector(vlib_main_t *vm, virtio_if_t *vif, u16 queue_msix_vector, u16 queue_id)
static void virtio_pci_modern_set_status(vlib_main_t *vm, virtio_if_t *vif, u8 status)
vl_api_address_t dst
Definition: gre.api:55
vring_desc_t * desc
Definition: virtio_std.h:175
static u16 virtio_pci_modern_get_device_mtu(vlib_main_t *vm, virtio_if_t *vif)
#define virtio_log_debug(vif, f,...)
Definition: virtio.h:272
static u8 virtio_pci_modern_setup_queue(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id, void *p)
u8 len
Definition: ip_types.api:103
#define VIRTIO_PCI_VRING_ALIGN
Definition: pci.h:90
static u64 virtio_pci_modern_get_queue_driver(virtio_if_t *vif)
static void virtio_pci_modern_set_queue_device(virtio_if_t *vif, u64 queue_device)
#define clib_warning(format, args...)
Definition: error.h:59
static_always_inline void vring_init(vring_t *vr, u32 num, void *p, u32 align)
Definition: virtio_std.h:181
static void virtio_pci_modern_set_queue_driver(virtio_if_t *vif, u64 queue_driver)
static u8 virtio_pci_modern_get_config_generation(virtio_if_t *vif)
static u64 virtio_pci_modern_get_device_features(vlib_main_t *vm, virtio_if_t *vif)
static void virtio_pci_modern_set_queue_size(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id, u16 queue_size)
static u16 virtio_pci_modern_get_msix_config(virtio_if_t *vif)
static u64 virtio_pci_modern_get_driver_features(vlib_main_t *vm, virtio_if_t *vif)
static u8 virtio_pci_modern_get_isr(vlib_main_t *vm, virtio_if_t *vif)
#define VIRTIO_QUEUE_SIZE_OFFSET(v)
vring_packed_desc_t * packed_desc
Definition: virtio.h:77
#define VIRTIO_FEATURE_SELECT_HI
static void virtio_pci_modern_device_debug_config_space(vlib_main_t *vm, virtio_if_t *vif)
static u16 virtio_pci_modern_get_device_status(vlib_main_t *vm, virtio_if_t *vif)
#define VIRTIO_QUEUE_DESC_OFFSET(v)
u32 mac_addr32
Definition: virtio.h:167
#define VIRTIO_MTU_OFFSET(v)
static uword is_pow2(uword x)
Definition: clib.h:253
static void virtio_pci_modern_del_queue(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id)
#define VIRTIO_DEVICE_FEATURE_OFFSET(v)
static u64 vlib_physmem_get_pa(vlib_main_t *vm, void *mem)
static void virtio_pci_modern_write_config(vlib_main_t *vm, virtio_if_t *vif, void *src, int len, u32 addr)
#define VIRTIO_MSIX_CONFIG_VECTOR_OFFSET(v)
struct _virtio_pci_func virtio_pci_func_t
static void virtio_pci_modern_set_queue_select(virtio_if_t *vif, u16 queue_select)
#define VIRTIO_QUEUE_ENABLE_OFFSET(v)
#define VIRTIO_MAC_OFFSET(v)
static u16 virtio_pci_modern_set_msix_config(vlib_main_t *vm, virtio_if_t *vif, u16 msix_config)
u16 mac_addr16
Definition: virtio.h:168
int is_packed
Definition: virtio.h:210
static void virtio_pci_modern_get_device_mac(vlib_main_t *vm, virtio_if_t *vif)
#define VIRTIO_NOTIFICATION_OFFSET(v)
static u64 virtio_pci_modern_get_queue_device(virtio_if_t *vif)
static void virtio_pci_modern_set_queue_desc(virtio_if_t *vif, u64 queue_desc)
static void virtio_pci_modern_set_device_mac(vlib_main_t *vm, virtio_if_t *vif)
static u16 virtio_pci_modern_get_queue_msix_vector(virtio_if_t *vif)
#define VIRTIO_DRIVER_FEATURE_SELECT_OFFSET(v)
#define VIRTIO_DEVICE_FEATURE_SELECT_OFFSET(v)
static u16 virtio_pci_modern_get_queue_notify_off(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id)