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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <sys/ioctl.h>
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>
25 #include <vnet/devices/virtio/virtio.h>
26 #include <vnet/devices/virtio/virtio_pci_modern.h>
27 #include <vnet/devices/virtio/pci.h>
31 virtio_pci_modern_get_device_features (vlib_main_t * vm, virtio_if_t * vif)
33 u64 features_lo, features_hi;
34 virtio_pci_reg_write_u32 (vif, VIRTIO_DEVICE_FEATURE_SELECT_OFFSET (vif),
35 VIRTIO_FEATURE_SELECT_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),
39 VIRTIO_FEATURE_SELECT_HI);
41 virtio_pci_reg_read_u32 (vif, VIRTIO_DEVICE_FEATURE_OFFSET (vif));
42 u64 features = ((features_hi << 32) | features_lo);
47 virtio_pci_modern_get_driver_features (vlib_main_t * vm, virtio_if_t * vif)
49 u64 features_lo, features_hi;
50 virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_SELECT_OFFSET (vif),
51 VIRTIO_FEATURE_SELECT_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),
55 VIRTIO_FEATURE_SELECT_HI);
57 virtio_pci_reg_read_u32 (vif, VIRTIO_DRIVER_FEATURE_OFFSET (vif));
59 vif->features = ((features_hi << 32) | features_lo);
64 virtio_pci_modern_set_driver_features (vlib_main_t * vm, virtio_if_t * vif,
67 u32 features_lo = (u32) features, features_hi = (u32) (features >> 32);
68 virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_SELECT_OFFSET (vif),
69 VIRTIO_FEATURE_SELECT_LO);
70 virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_OFFSET (vif),
72 virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_SELECT_OFFSET (vif),
73 VIRTIO_FEATURE_SELECT_HI);
74 virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_OFFSET (vif),
77 if (features != virtio_pci_modern_get_driver_features (vm, vif))
79 clib_warning ("modern set guest features failed!");
84 virtio_pci_modern_get_msix_config (virtio_if_t * vif)
88 virtio_pci_reg_read_u16 (vif, VIRTIO_MSIX_CONFIG_VECTOR_OFFSET (vif));
93 virtio_pci_modern_set_msix_config (vlib_main_t * vm, virtio_if_t * vif,
96 virtio_pci_reg_write_u16 (vif, VIRTIO_MSIX_CONFIG_VECTOR_OFFSET (vif),
98 return virtio_pci_modern_get_msix_config (vif);
102 virtio_pci_modern_get_num_queues (virtio_if_t * vif)
105 num_queues = virtio_pci_reg_read_u16 (vif, VIRTIO_NUM_QUEUES_OFFSET (vif));
110 virtio_pci_modern_get_status (vlib_main_t * vm, virtio_if_t * vif)
113 status = virtio_pci_reg_read_u8 (vif, VIRTIO_DEVICE_STATUS_OFFSET (vif));
118 virtio_pci_modern_set_status (vlib_main_t * vm, virtio_if_t * vif, u8 status)
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);
126 virtio_pci_modern_reset (vlib_main_t * vm, virtio_if_t * vif)
128 virtio_pci_modern_set_status (vm, vif, VIRTIO_CONFIG_STATUS_RESET);
129 return virtio_pci_modern_get_status (vm, vif);
133 virtio_pci_modern_get_config_generation (virtio_if_t * vif)
135 u8 config_generation = 0;
137 virtio_pci_reg_read_u8 (vif, VIRTIO_CONFIG_GENERATION_OFFSET (vif));
138 return config_generation;
142 virtio_pci_modern_set_queue_select (virtio_if_t * vif, u16 queue_select)
144 virtio_pci_reg_write_u16 (vif, VIRTIO_QUEUE_SELECT_OFFSET (vif),
149 virtio_pci_modern_get_queue_size (vlib_main_t * vm, virtio_if_t * vif,
153 virtio_pci_modern_set_queue_select (vif, queue_id);
154 queue_size = virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_SIZE_OFFSET (vif));
159 virtio_pci_modern_set_queue_size (vlib_main_t * vm, virtio_if_t * vif,
160 u16 queue_id, u16 queue_size)
162 if (!is_pow2 (queue_size))
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),
173 virtio_pci_modern_get_queue_msix_vector (virtio_if_t * vif)
175 u16 queue_msix_vector = 0;
177 virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_MSIX_VECTOR_OFFSET (vif));
178 return queue_msix_vector;
182 virtio_pci_modern_set_queue_msix_vector (vlib_main_t * vm, virtio_if_t * vif,
183 u16 queue_msix_vector, u16 queue_id)
185 virtio_pci_modern_set_queue_select (vif, queue_id);
186 virtio_pci_reg_write_u16 (vif, VIRTIO_QUEUE_MSIX_VECTOR_OFFSET (vif),
188 return virtio_pci_modern_get_queue_msix_vector (vif);
192 virtio_pci_modern_get_queue_enable (virtio_if_t * vif, u16 queue_id)
194 u16 queue_enable = 0;
195 virtio_pci_modern_set_queue_select (vif, queue_id);
197 virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_ENABLE_OFFSET (vif));
202 virtio_pci_modern_set_queue_enable (virtio_if_t * vif, u16 queue_id,
205 virtio_pci_modern_set_queue_select (vif, queue_id);
206 virtio_pci_reg_write_u16 (vif, VIRTIO_QUEUE_ENABLE_OFFSET (vif),
211 virtio_pci_modern_get_queue_notify_off (virtio_if_t * vif, u16 queue_id)
213 u16 queue_notify_off = 0;
214 virtio_pci_modern_set_queue_select (vif, queue_id);
216 virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_NOTIFY_OFF_OFFSET (vif));
217 return queue_notify_off;
221 virtio_pci_modern_get_queue_desc (virtio_if_t * vif)
224 queue_desc = virtio_pci_reg_read_u64 (vif, VIRTIO_QUEUE_DESC_OFFSET (vif));
229 virtio_pci_modern_set_queue_desc (virtio_if_t * vif, u64 queue_desc)
231 virtio_pci_reg_write_u64 (vif, VIRTIO_QUEUE_DESC_OFFSET (vif), queue_desc);
235 virtio_pci_modern_get_queue_driver (virtio_if_t * vif)
237 u64 queue_driver = 0;
239 virtio_pci_reg_read_u64 (vif, VIRTIO_QUEUE_DRIVER_OFFSET (vif));
244 virtio_pci_modern_set_queue_driver (virtio_if_t * vif, u64 queue_driver)
246 virtio_pci_reg_write_u64 (vif, VIRTIO_QUEUE_DRIVER_OFFSET (vif),
251 virtio_pci_modern_get_queue_device (virtio_if_t * vif)
253 u64 queue_device = 0;
255 virtio_pci_reg_read_u64 (vif, VIRTIO_QUEUE_DEVICE_OFFSET (vif));
260 virtio_pci_modern_set_queue_device (virtio_if_t * vif, u64 queue_device)
262 virtio_pci_reg_write_u64 (vif, VIRTIO_QUEUE_DEVICE_OFFSET (vif),
267 virtio_pci_modern_setup_queue (vlib_main_t * vm, virtio_if_t * vif,
268 u16 queue_id, void *p)
273 virtio_pci_modern_set_queue_select (vif, queue_id);
274 queue_size = virtio_pci_modern_get_queue_size (vm, vif, queue_id);
275 vring_init (&vr, queue_size, p, VIRTIO_PCI_VRING_ALIGN);
277 u64 desc = vlib_physmem_get_pa (vm, vr.desc);
278 virtio_pci_modern_set_queue_desc (vif, desc);
279 if (desc != virtio_pci_modern_get_queue_desc (vif))
282 u64 avail = vlib_physmem_get_pa (vm, vr.avail);
283 virtio_pci_modern_set_queue_driver (vif, avail);
284 if (avail != virtio_pci_modern_get_queue_driver (vif))
287 u64 used = vlib_physmem_get_pa (vm, vr.used);
288 virtio_pci_modern_set_queue_device (vif, used);
289 if (used != virtio_pci_modern_get_queue_device (vif))
292 virtio_pci_modern_set_queue_enable (vif, queue_id, 1);
294 if (virtio_pci_modern_get_queue_enable (vif, queue_id))
301 virtio_pci_modern_del_queue (vlib_main_t * vm, virtio_if_t * vif,
304 virtio_pci_modern_set_queue_select (vif, queue_id);
305 virtio_pci_modern_set_queue_enable (vif, queue_id, 0);
306 virtio_pci_modern_set_queue_desc (vif, 0);
307 virtio_pci_modern_set_queue_driver (vif, 0);
308 virtio_pci_modern_set_queue_device (vif, 0);
312 virtio_pci_modern_get_device_mac (vlib_main_t * vm, virtio_if_t * vif)
314 *((u32 *) vif->mac_addr) =
315 virtio_pci_reg_read_u32 (vif, VIRTIO_MAC_OFFSET (vif));
316 *((u16 *) (vif->mac_addr + 4)) =
317 virtio_pci_reg_read_u16 (vif, VIRTIO_MAC_OFFSET (vif) + 4);
321 virtio_pci_modern_set_device_mac (vlib_main_t * vm, virtio_if_t * vif)
323 virtio_pci_reg_write_u32 (vif, VIRTIO_MAC_OFFSET (vif),
324 *((u32 *) vif->mac_addr));
325 virtio_pci_reg_write_u16 (vif, VIRTIO_MAC_OFFSET (vif) + 4,
326 *((u16 *) (vif->mac_addr + 4)));
330 virtio_pci_modern_get_device_status (vlib_main_t * vm, virtio_if_t * vif)
333 status = virtio_pci_reg_read_u16 (vif, VIRTIO_STATUS_OFFSET (vif));
338 virtio_pci_modern_get_max_virtqueue_pairs (vlib_main_t * vm,
341 u16 max_virtqueue_pairs = 0;
342 max_virtqueue_pairs =
343 virtio_pci_reg_read_u16 (vif, VIRTIO_MAX_VIRTQUEUE_PAIRS_OFFSET (vif));
344 u16 supported_queues = virtio_pci_modern_get_num_queues (vif);
345 virtio_log_debug (vif, "max-virtqueue-pairs %u, supported-queues %u",
346 max_virtqueue_pairs, supported_queues);
347 return max_virtqueue_pairs;
351 virtio_pci_modern_get_device_mtu (vlib_main_t * vm, virtio_if_t * vif)
354 mtu = virtio_pci_reg_read_u16 (vif, VIRTIO_MTU_OFFSET (vif));
359 virtio_pci_modern_read_config (vlib_main_t * vm, virtio_if_t * vif, void *dst,
365 config_count = virtio_pci_modern_get_config_generation (vif);
366 virtio_pci_modern_get_device_mac (vm, vif);
367 u16 status = virtio_pci_modern_get_device_status (vm, vif);
368 u16 max_queue_pairs =
369 virtio_pci_modern_get_max_virtqueue_pairs (vm, vif);
370 u16 mtu = virtio_pci_modern_get_device_mtu (vm, vif);
371 virtio_log_debug (vif, "status %u, max_queue_pairs %u, mtu %u", status,
372 max_queue_pairs, mtu);
374 while (config_count != virtio_pci_modern_get_config_generation (vif));
378 virtio_pci_modern_write_config (vlib_main_t * vm, virtio_if_t * vif,
379 void *src, int len, u32 addr)
385 virtio_pci_modern_get_isr (vlib_main_t * vm, virtio_if_t * vif)
387 return virtio_pci_reg_read_u8 (vif, VIRTIO_ISR_OFFSET (vif));
391 virtio_pci_modern_notify_queue (vlib_main_t * vm, virtio_if_t * vif,
394 u16 queue_notify_off =
395 virtio_pci_modern_get_queue_notify_off (vif, queue_id);
396 virtio_pci_reg_write_u16 (vif,
397 VIRTIO_NOTIFICATION_OFFSET (vif) +
398 vif->notify_off_multiplier * queue_notify_off,
403 virtio_pci_modern_device_debug_config_space (vlib_main_t * vm,
406 // do nothing for now
409 const virtio_pci_func_t virtio_pci_modern_func = {
410 .read_config = virtio_pci_modern_read_config,
411 .write_config = virtio_pci_modern_write_config,
412 .get_device_features = virtio_pci_modern_get_device_features,
413 .get_driver_features = virtio_pci_modern_get_driver_features,
414 .set_driver_features = virtio_pci_modern_set_driver_features,
415 .get_status = virtio_pci_modern_get_status,
416 .set_status = virtio_pci_modern_set_status,
417 .device_reset = virtio_pci_modern_reset,
418 .get_isr = virtio_pci_modern_get_isr,
419 .get_queue_size = virtio_pci_modern_get_queue_size,
420 .set_queue_size = virtio_pci_modern_set_queue_size,
421 .setup_queue = virtio_pci_modern_setup_queue,
422 .del_queue = virtio_pci_modern_del_queue,
423 .notify_queue = virtio_pci_modern_notify_queue,
424 .set_config_irq = virtio_pci_modern_set_msix_config,
425 .set_queue_irq = virtio_pci_modern_set_queue_msix_vector,
426 .get_mac = virtio_pci_modern_get_device_mac,
427 .set_mac = virtio_pci_modern_set_device_mac,
428 .get_device_status = virtio_pci_modern_get_device_status,
429 .get_max_queue_pairs = virtio_pci_modern_get_max_virtqueue_pairs,
430 .get_mtu = virtio_pci_modern_get_device_mtu,
431 .device_debug_config_space = virtio_pci_modern_device_debug_config_space,
435 * fd.io coding-style-patch-verification: ON
438 * eval: (c-set-style "gnu")