2 * Copyright (c) 2018 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.
16 #include <vlib/vlib.h>
17 #include <vlib/pci/pci.h>
18 #include <vnet/ethernet/ethernet.h>
19 #include <vnet/ip/ip4_packet.h>
20 #include <vnet/ip/ip6_packet.h>
21 #include <vnet/devices/virtio/virtio.h>
22 #include <vnet/devices/virtio/virtio_pci_legacy.h>
23 #include <vnet/devices/virtio/pci.h>
25 #define PCI_CONFIG_SIZE(vif) ((vif->msix_enabled == VIRTIO_MSIX_ENABLED) ? \
29 virtio_pci_legacy_read_config (vlib_main_t * vm, virtio_if_t * vif, void *dst,
33 vlib_pci_dev_handle_t h = vif->pci_dev_handle;
40 vlib_pci_read_io_u32 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
45 vlib_pci_read_io_u16 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
50 vlib_pci_read_io_u8 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
52 dst = (u8 *) dst + size;
59 virtio_pci_legacy_write_config (vlib_main_t * vm, virtio_if_t * vif,
60 void *src, int len, u32 addr)
63 vlib_pci_dev_handle_t h = vif->pci_dev_handle;
70 vlib_pci_write_io_u32 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
75 vlib_pci_write_io_u16 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
80 vlib_pci_write_io_u8 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
82 src = (u8 *) src + size;
89 virtio_pci_legacy_get_host_features (vlib_main_t * vm, virtio_if_t * vif)
92 vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_HOST_FEATURES,
98 virtio_pci_legacy_get_guest_features (vlib_main_t * vm, virtio_if_t * vif)
100 u32 guest_features = 0;
101 vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
103 vif->features = guest_features;
104 return guest_features;
108 virtio_pci_legacy_set_guest_features (vlib_main_t * vm, virtio_if_t * vif,
111 if ((guest_features >> 32) != 0)
113 clib_warning ("only 32 bit features are allowed for legacy virtio!");
116 u32 gf = (u32) guest_features;
118 vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
120 vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
122 if (features != (u32) guest_features)
124 clib_warning ("legacy set guest features failed!");
129 virtio_pci_legacy_get_status (vlib_main_t * vm, virtio_if_t * vif)
132 vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_STATUS, &status);
137 virtio_pci_legacy_set_status (vlib_main_t * vm, virtio_if_t * vif, u8 status)
139 if (status != VIRTIO_CONFIG_STATUS_RESET)
140 status |= virtio_pci_legacy_get_status (vm, vif);
141 vlib_pci_write_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_STATUS, &status);
145 virtio_pci_legacy_reset (vlib_main_t * vm, virtio_if_t * vif)
147 virtio_pci_legacy_set_status (vm, vif, VIRTIO_CONFIG_STATUS_RESET);
148 return virtio_pci_legacy_get_status (vm, vif);
152 virtio_pci_legacy_get_isr (vlib_main_t * vm, virtio_if_t * vif)
155 vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_ISR, &isr);
160 virtio_pci_legacy_get_queue_num (vlib_main_t * vm, virtio_if_t * vif,
164 vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
166 vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NUM,
172 virtio_pci_legacy_set_queue_num (vlib_main_t * vm, virtio_if_t * vif,
173 u16 queue_id, u16 queue_size)
179 virtio_pci_legacy_setup_queue (vlib_main_t *vm, virtio_if_t *vif, u16 queue_id,
180 vnet_virtio_vring_t *vring)
183 vlib_physmem_get_pa (vm, vring->desc) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
184 u32 addr2 = 0, a = (u32) addr;
185 vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
187 vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN, &a);
188 vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN,
193 clib_warning ("legacy queue setup failed!");
198 virtio_pci_legacy_del_queue (vlib_main_t * vm, virtio_if_t * vif,
202 vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
204 vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN, &src);
208 virtio_pci_legacy_get_queue_notify_off (vlib_main_t * vm, virtio_if_t * vif,
215 virtio_pci_legacy_notify_queue (vlib_main_t * vm, virtio_if_t * vif,
216 u16 queue_id, u16 queue_notify_off)
218 vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NOTIFY,
222 /* Enable one vector (0) for Link State Intrerrupt */
224 virtio_pci_legacy_set_config_irq (vlib_main_t * vm, virtio_if_t * vif,
227 vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
229 vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
235 virtio_pci_legacy_set_queue_irq (vlib_main_t * vm, virtio_if_t * vif, u16 vec,
238 vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
240 vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
242 vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
248 virtio_pci_legacy_get_mac (vlib_main_t * vm, virtio_if_t * vif)
250 virtio_pci_legacy_read_config (vm, vif, vif->mac_addr,
251 sizeof (vif->mac_addr), 0);
255 virtio_pci_legacy_set_mac (vlib_main_t * vm, virtio_if_t * vif)
257 virtio_pci_legacy_write_config (vm, vif, vif->mac_addr,
258 sizeof (vif->mac_addr), 0);
262 virtio_pci_legacy_get_device_status (vlib_main_t * vm, virtio_if_t * vif)
265 virtio_pci_legacy_read_config (vm, vif, &status,
268 (virtio_net_config_t, status));
273 virtio_pci_legacy_get_max_queue_pairs (vlib_main_t * vm, virtio_if_t * vif)
275 virtio_net_config_t config;
276 virtio_pci_legacy_read_config (vm, vif, &config.max_virtqueue_pairs,
277 sizeof (config.max_virtqueue_pairs),
279 (virtio_net_config_t, max_virtqueue_pairs));
280 return config.max_virtqueue_pairs;
284 virtio_pci_legacy_get_mtu (vlib_main_t * vm, virtio_if_t * vif)
286 virtio_net_config_t config;
287 virtio_pci_legacy_read_config (vm, vif, &config.mtu,
289 STRUCT_OFFSET_OF (virtio_net_config_t, mtu));
295 virtio_pci_legacy_device_debug_config_space (vlib_main_t * vm,
301 vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_HOST_FEATURES,
303 vlib_cli_output (vm, "remote features 0x%lx", data_u32);
304 vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
306 vlib_cli_output (vm, "guest features 0x%lx", data_u32);
307 vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN,
309 vlib_cli_output (vm, "queue address 0x%lx", data_u32);
310 vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NUM,
312 vlib_cli_output (vm, "queue size 0x%x", data_u16);
313 vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
315 vlib_cli_output (vm, "queue select 0x%x", data_u16);
316 vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NOTIFY,
318 vlib_cli_output (vm, "queue notify 0x%x", data_u16);
319 vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_STATUS, &data_u8);
320 vlib_cli_output (vm, "status 0x%x", data_u8);
321 vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_ISR, &data_u8);
322 vlib_cli_output (vm, "isr 0x%x", data_u8);
324 if (vif->msix_enabled == VIRTIO_MSIX_ENABLED)
326 vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
328 vlib_cli_output (vm, "config vector 0x%x", data_u16);
330 vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
332 vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
334 vlib_cli_output (vm, "queue vector for queue (0) 0x%x", data_u16);
338 virtio_pci_legacy_read_config (vm, vif, mac, sizeof (mac), 0);
339 vlib_cli_output (vm, "mac %U", format_ethernet_address, mac);
340 virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16), /* offset to status */
342 vlib_cli_output (vm, "link up/down status 0x%x", data_u16);
343 virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16),
344 /* offset to max_virtqueue */ 8);
345 vlib_cli_output (vm, "num of virtqueue 0x%x", data_u16);
346 virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16), /* offset to mtu */
348 vlib_cli_output (vm, "mtu 0x%x", data_u16);
350 u32 i = PCI_CONFIG_SIZE (vif) + 12, a = 4;
353 for (; i < 64; i += 4)
356 vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, i, &data);
357 vlib_cli_output (vm, "0x%lx", data);
361 const virtio_pci_func_t virtio_pci_legacy_func = {
362 .read_config = virtio_pci_legacy_read_config,
363 .write_config = virtio_pci_legacy_write_config,
364 .get_device_features = virtio_pci_legacy_get_host_features,
365 .get_driver_features = virtio_pci_legacy_get_guest_features,
366 .set_driver_features = virtio_pci_legacy_set_guest_features,
367 .get_status = virtio_pci_legacy_get_status,
368 .set_status = virtio_pci_legacy_set_status,
369 .device_reset = virtio_pci_legacy_reset,
370 .get_isr = virtio_pci_legacy_get_isr,
371 .get_queue_size = virtio_pci_legacy_get_queue_num,
372 .set_queue_size = virtio_pci_legacy_set_queue_num,
373 .setup_queue = virtio_pci_legacy_setup_queue,
374 .del_queue = virtio_pci_legacy_del_queue,
375 .get_queue_notify_off = virtio_pci_legacy_get_queue_notify_off,
376 .notify_queue = virtio_pci_legacy_notify_queue,
377 .set_config_irq = virtio_pci_legacy_set_config_irq,
378 .set_queue_irq = virtio_pci_legacy_set_queue_irq,
379 .get_mac = virtio_pci_legacy_get_mac,
380 .set_mac = virtio_pci_legacy_set_mac,
381 .get_device_status = virtio_pci_legacy_get_device_status,
382 .get_max_queue_pairs = virtio_pci_legacy_get_max_queue_pairs,
383 .get_mtu = virtio_pci_legacy_get_mtu,
384 .device_debug_config_space = virtio_pci_legacy_device_debug_config_space,
388 * fd.io coding-style-patch-verification: ON
391 * eval: (c-set-style "gnu")