LCOV - code coverage report
Current view: top level - vnet/devices/virtio - virtio_pci_modern.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 181 0.0 %
Date: 2023-07-05 22:20:52 Functions: 0 36 0.0 %

          Line data    Source code
       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>
      25             : #include <vnet/devices/virtio/virtio.h>
      26             : #include <vnet/devices/virtio/virtio_pci_modern.h>
      27             : #include <vnet/devices/virtio/pci.h>
      28             : 
      29             : 
      30             : static u64
      31           0 : virtio_pci_modern_get_device_features (vlib_main_t * vm, virtio_if_t * vif)
      32             : {
      33             :   u64 features_lo, features_hi;
      34           0 :   virtio_pci_reg_write_u32 (vif, VIRTIO_DEVICE_FEATURE_SELECT_OFFSET (vif),
      35             :                             VIRTIO_FEATURE_SELECT_LO);
      36           0 :   features_lo =
      37           0 :     virtio_pci_reg_read_u32 (vif, VIRTIO_DEVICE_FEATURE_OFFSET (vif));
      38           0 :   virtio_pci_reg_write_u32 (vif, VIRTIO_DEVICE_FEATURE_SELECT_OFFSET (vif),
      39             :                             VIRTIO_FEATURE_SELECT_HI);
      40           0 :   features_hi =
      41           0 :     virtio_pci_reg_read_u32 (vif, VIRTIO_DEVICE_FEATURE_OFFSET (vif));
      42           0 :   u64 features = ((features_hi << 32) | features_lo);
      43           0 :   return features;
      44             : }
      45             : 
      46             : static u64
      47           0 : virtio_pci_modern_get_driver_features (vlib_main_t * vm, virtio_if_t * vif)
      48             : {
      49             :   u64 features_lo, features_hi;
      50           0 :   virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_SELECT_OFFSET (vif),
      51             :                             VIRTIO_FEATURE_SELECT_LO);
      52           0 :   features_lo =
      53           0 :     virtio_pci_reg_read_u32 (vif, VIRTIO_DRIVER_FEATURE_OFFSET (vif));
      54           0 :   virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_SELECT_OFFSET (vif),
      55             :                             VIRTIO_FEATURE_SELECT_HI);
      56           0 :   features_hi =
      57           0 :     virtio_pci_reg_read_u32 (vif, VIRTIO_DRIVER_FEATURE_OFFSET (vif));
      58             : 
      59           0 :   vif->features = ((features_hi << 32) | features_lo);
      60           0 :   return vif->features;
      61             : }
      62             : 
      63             : static void
      64           0 : virtio_pci_modern_set_driver_features (vlib_main_t * vm, virtio_if_t * vif,
      65             :                                        u64 features)
      66             : {
      67           0 :   u32 features_lo = (u32) features, features_hi = (u32) (features >> 32);
      68           0 :   virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_SELECT_OFFSET (vif),
      69             :                             VIRTIO_FEATURE_SELECT_LO);
      70           0 :   virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_OFFSET (vif),
      71             :                             features_lo);
      72           0 :   virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_SELECT_OFFSET (vif),
      73             :                             VIRTIO_FEATURE_SELECT_HI);
      74           0 :   virtio_pci_reg_write_u32 (vif, VIRTIO_DRIVER_FEATURE_OFFSET (vif),
      75             :                             features_hi);
      76             : 
      77           0 :   if (features != virtio_pci_modern_get_driver_features (vm, vif))
      78             :     {
      79           0 :       clib_warning ("modern set guest features failed!");
      80             :     }
      81           0 : }
      82             : 
      83             : static u16
      84           0 : virtio_pci_modern_get_msix_config (virtio_if_t * vif)
      85             : {
      86             :   u16 msix_config;
      87             :   msix_config =
      88           0 :     virtio_pci_reg_read_u16 (vif, VIRTIO_MSIX_CONFIG_VECTOR_OFFSET (vif));
      89           0 :   return msix_config;
      90             : }
      91             : 
      92             : static u16
      93           0 : virtio_pci_modern_set_msix_config (vlib_main_t * vm, virtio_if_t * vif,
      94             :                                    u16 msix_config)
      95             : {
      96           0 :   virtio_pci_reg_write_u16 (vif, VIRTIO_MSIX_CONFIG_VECTOR_OFFSET (vif),
      97             :                             msix_config);
      98           0 :   return virtio_pci_modern_get_msix_config (vif);
      99             : }
     100             : 
     101             : static u16
     102           0 : virtio_pci_modern_get_num_queues (virtio_if_t * vif)
     103             : {
     104           0 :   u16 num_queues = 0;
     105           0 :   num_queues = virtio_pci_reg_read_u16 (vif, VIRTIO_NUM_QUEUES_OFFSET (vif));
     106           0 :   return num_queues;
     107             : }
     108             : 
     109             : static u8
     110           0 : virtio_pci_modern_get_status (vlib_main_t * vm, virtio_if_t * vif)
     111             : {
     112           0 :   u8 status = 0;
     113           0 :   status = virtio_pci_reg_read_u8 (vif, VIRTIO_DEVICE_STATUS_OFFSET (vif));
     114           0 :   return status;
     115             : }
     116             : 
     117             : static void
     118           0 : virtio_pci_modern_set_status (vlib_main_t * vm, virtio_if_t * vif, u8 status)
     119             : {
     120           0 :   if (status != VIRTIO_CONFIG_STATUS_RESET)
     121           0 :     status |= virtio_pci_modern_get_status (vm, vif);
     122           0 :   virtio_pci_reg_write_u8 (vif, VIRTIO_DEVICE_STATUS_OFFSET (vif), status);
     123           0 : }
     124             : 
     125             : static u8
     126           0 : virtio_pci_modern_reset (vlib_main_t * vm, virtio_if_t * vif)
     127             : {
     128           0 :   virtio_pci_modern_set_status (vm, vif, VIRTIO_CONFIG_STATUS_RESET);
     129           0 :   return virtio_pci_modern_get_status (vm, vif);
     130             : }
     131             : 
     132             : static u8
     133           0 : virtio_pci_modern_get_config_generation (virtio_if_t * vif)
     134             : {
     135           0 :   u8 config_generation = 0;
     136             :   config_generation =
     137           0 :     virtio_pci_reg_read_u8 (vif, VIRTIO_CONFIG_GENERATION_OFFSET (vif));
     138           0 :   return config_generation;
     139             : }
     140             : 
     141             : static void
     142           0 : virtio_pci_modern_set_queue_select (virtio_if_t * vif, u16 queue_select)
     143             : {
     144           0 :   virtio_pci_reg_write_u16 (vif, VIRTIO_QUEUE_SELECT_OFFSET (vif),
     145             :                             queue_select);
     146           0 : }
     147             : 
     148             : static u16
     149           0 : virtio_pci_modern_get_queue_size (vlib_main_t * vm, virtio_if_t * vif,
     150             :                                   u16 queue_id)
     151             : {
     152           0 :   u16 queue_size = 0;
     153           0 :   virtio_pci_modern_set_queue_select (vif, queue_id);
     154           0 :   queue_size = virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_SIZE_OFFSET (vif));
     155           0 :   return queue_size;
     156             : }
     157             : 
     158             : static void
     159           0 : virtio_pci_modern_set_queue_size (vlib_main_t * vm, virtio_if_t * vif,
     160             :                                   u16 queue_id, u16 queue_size)
     161             : {
     162           0 :   if (!is_pow2 (queue_size))
     163             :     {
     164           0 :       return;
     165             :     }
     166             : 
     167           0 :   if (virtio_pci_modern_get_queue_size (vm, vif, queue_id) > queue_size)
     168           0 :     virtio_pci_reg_write_u16 (vif, VIRTIO_QUEUE_SIZE_OFFSET (vif),
     169             :                               queue_size);
     170             : }
     171             : 
     172             : static u16
     173           0 : virtio_pci_modern_get_queue_msix_vector (virtio_if_t * vif)
     174             : {
     175           0 :   u16 queue_msix_vector = 0;
     176             :   queue_msix_vector =
     177           0 :     virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_MSIX_VECTOR_OFFSET (vif));
     178           0 :   return queue_msix_vector;
     179             : }
     180             : 
     181             : static u16
     182           0 : virtio_pci_modern_set_queue_msix_vector (vlib_main_t * vm, virtio_if_t * vif,
     183             :                                          u16 queue_msix_vector, u16 queue_id)
     184             : {
     185           0 :   virtio_pci_modern_set_queue_select (vif, queue_id);
     186           0 :   virtio_pci_reg_write_u16 (vif, VIRTIO_QUEUE_MSIX_VECTOR_OFFSET (vif),
     187             :                             queue_msix_vector);
     188           0 :   return virtio_pci_modern_get_queue_msix_vector (vif);
     189             : }
     190             : 
     191             : static u16
     192           0 : virtio_pci_modern_get_queue_enable (virtio_if_t * vif, u16 queue_id)
     193             : {
     194           0 :   u16 queue_enable = 0;
     195           0 :   virtio_pci_modern_set_queue_select (vif, queue_id);
     196             :   queue_enable =
     197           0 :     virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_ENABLE_OFFSET (vif));
     198           0 :   return queue_enable;
     199             : }
     200             : 
     201             : static void
     202           0 : virtio_pci_modern_set_queue_enable (virtio_if_t * vif, u16 queue_id,
     203             :                                     u16 queue_enable)
     204             : {
     205           0 :   virtio_pci_modern_set_queue_select (vif, queue_id);
     206           0 :   virtio_pci_reg_write_u16 (vif, VIRTIO_QUEUE_ENABLE_OFFSET (vif),
     207             :                             queue_enable);
     208           0 : }
     209             : 
     210             : static u16
     211           0 : virtio_pci_modern_get_queue_notify_off (vlib_main_t * vm, virtio_if_t * vif,
     212             :                                         u16 queue_id)
     213             : {
     214           0 :   u16 queue_notify_off = 0;
     215           0 :   virtio_pci_modern_set_queue_select (vif, queue_id);
     216             :   queue_notify_off =
     217           0 :     virtio_pci_reg_read_u16 (vif, VIRTIO_QUEUE_NOTIFY_OFF_OFFSET (vif));
     218           0 :   return queue_notify_off;
     219             : }
     220             : 
     221             : static u64
     222           0 : virtio_pci_modern_get_queue_desc (virtio_if_t * vif)
     223             : {
     224           0 :   u64 queue_desc = 0;
     225           0 :   queue_desc = virtio_pci_reg_read_u64 (vif, VIRTIO_QUEUE_DESC_OFFSET (vif));
     226           0 :   return queue_desc;
     227             : }
     228             : 
     229             : static void
     230           0 : virtio_pci_modern_set_queue_desc (virtio_if_t * vif, u64 queue_desc)
     231             : {
     232           0 :   virtio_pci_reg_write_u64 (vif, VIRTIO_QUEUE_DESC_OFFSET (vif), queue_desc);
     233           0 : }
     234             : 
     235             : static u64
     236           0 : virtio_pci_modern_get_queue_driver (virtio_if_t * vif)
     237             : {
     238           0 :   u64 queue_driver = 0;
     239             :   queue_driver =
     240           0 :     virtio_pci_reg_read_u64 (vif, VIRTIO_QUEUE_DRIVER_OFFSET (vif));
     241           0 :   return queue_driver;
     242             : }
     243             : 
     244             : static void
     245           0 : virtio_pci_modern_set_queue_driver (virtio_if_t * vif, u64 queue_driver)
     246             : {
     247           0 :   virtio_pci_reg_write_u64 (vif, VIRTIO_QUEUE_DRIVER_OFFSET (vif),
     248             :                             queue_driver);
     249           0 : }
     250             : 
     251             : static u64
     252           0 : virtio_pci_modern_get_queue_device (virtio_if_t * vif)
     253             : {
     254           0 :   u64 queue_device = 0;
     255             :   queue_device =
     256           0 :     virtio_pci_reg_read_u64 (vif, VIRTIO_QUEUE_DEVICE_OFFSET (vif));
     257           0 :   return queue_device;
     258             : }
     259             : 
     260             : static void
     261           0 : virtio_pci_modern_set_queue_device (virtio_if_t * vif, u64 queue_device)
     262             : {
     263           0 :   virtio_pci_reg_write_u64 (vif, VIRTIO_QUEUE_DEVICE_OFFSET (vif),
     264             :                             queue_device);
     265           0 : }
     266             : 
     267             : static u8
     268           0 : virtio_pci_modern_setup_queue (vlib_main_t *vm, virtio_if_t *vif, u16 queue_id,
     269             :                                vnet_virtio_vring_t *vring)
     270             : {
     271             :   u64 desc, avail, used;
     272             : 
     273           0 :   virtio_pci_modern_set_queue_select (vif, queue_id);
     274             : 
     275           0 :   if (vif->is_packed)
     276             :     {
     277           0 :       desc = vlib_physmem_get_pa (vm, vring->packed_desc);
     278           0 :       avail = vlib_physmem_get_pa (vm, vring->driver_event);
     279           0 :       used = vlib_physmem_get_pa (vm, vring->device_event);
     280             :     }
     281             :   else
     282             :     {
     283           0 :       desc = vlib_physmem_get_pa (vm, vring->desc);
     284           0 :       avail = vlib_physmem_get_pa (vm, vring->avail);
     285           0 :       used = vlib_physmem_get_pa (vm, vring->used);
     286             :     }
     287             : 
     288           0 :   virtio_pci_modern_set_queue_desc (vif, desc);
     289           0 :   if (desc != virtio_pci_modern_get_queue_desc (vif))
     290           0 :     return 1;
     291             : 
     292           0 :   virtio_pci_modern_set_queue_driver (vif, avail);
     293           0 :   if (avail != virtio_pci_modern_get_queue_driver (vif))
     294           0 :     return 1;
     295             : 
     296           0 :   virtio_pci_modern_set_queue_device (vif, used);
     297           0 :   if (used != virtio_pci_modern_get_queue_device (vif))
     298           0 :     return 1;
     299             : 
     300           0 :   virtio_pci_modern_set_queue_enable (vif, queue_id, 1);
     301             : 
     302           0 :   if (virtio_pci_modern_get_queue_enable (vif, queue_id))
     303           0 :     return 0;
     304             : 
     305           0 :   return 1;
     306             : }
     307             : 
     308             : static void
     309           0 : virtio_pci_modern_del_queue (vlib_main_t * vm, virtio_if_t * vif,
     310             :                              u16 queue_id)
     311             : {
     312           0 :   virtio_pci_modern_set_queue_select (vif, queue_id);
     313           0 :   virtio_pci_modern_set_queue_enable (vif, queue_id, 0);
     314           0 :   virtio_pci_modern_set_queue_desc (vif, 0);
     315           0 :   virtio_pci_modern_set_queue_driver (vif, 0);
     316           0 :   virtio_pci_modern_set_queue_device (vif, 0);
     317           0 : }
     318             : 
     319             : static void
     320           0 : virtio_pci_modern_get_device_mac (vlib_main_t * vm, virtio_if_t * vif)
     321             : {
     322           0 :   vif->mac_addr32 = virtio_pci_reg_read_u32 (vif, VIRTIO_MAC_OFFSET (vif));
     323           0 :   vif->mac_addr16 =
     324           0 :     virtio_pci_reg_read_u16 (vif, VIRTIO_MAC_OFFSET (vif) + 4);
     325           0 : }
     326             : 
     327             : static void
     328           0 : virtio_pci_modern_set_device_mac (vlib_main_t * vm, virtio_if_t * vif)
     329             : {
     330           0 :   virtio_pci_reg_write_u32 (vif, VIRTIO_MAC_OFFSET (vif), vif->mac_addr32);
     331           0 :   virtio_pci_reg_write_u16 (vif, VIRTIO_MAC_OFFSET (vif) + 4,
     332           0 :                             vif->mac_addr16);
     333           0 : }
     334             : 
     335             : static u16
     336           0 : virtio_pci_modern_get_device_status (vlib_main_t * vm, virtio_if_t * vif)
     337             : {
     338           0 :   u16 status = 0;
     339           0 :   status = virtio_pci_reg_read_u16 (vif, VIRTIO_STATUS_OFFSET (vif));
     340           0 :   return status;
     341             : }
     342             : 
     343             : static u16
     344           0 : virtio_pci_modern_get_max_virtqueue_pairs (vlib_main_t * vm,
     345             :                                            virtio_if_t * vif)
     346             : {
     347           0 :   u16 max_virtqueue_pairs = 0;
     348             :   max_virtqueue_pairs =
     349           0 :     virtio_pci_reg_read_u16 (vif, VIRTIO_MAX_VIRTQUEUE_PAIRS_OFFSET (vif));
     350           0 :   u16 supported_queues = virtio_pci_modern_get_num_queues (vif);
     351           0 :   virtio_log_debug (vif, "max-virtqueue-pairs %u, supported-queues %u",
     352             :                     max_virtqueue_pairs, supported_queues);
     353           0 :   return max_virtqueue_pairs;
     354             : }
     355             : 
     356             : static u16
     357           0 : virtio_pci_modern_get_device_mtu (vlib_main_t * vm, virtio_if_t * vif)
     358             : {
     359           0 :   u16 mtu = 0;
     360           0 :   mtu = virtio_pci_reg_read_u16 (vif, VIRTIO_MTU_OFFSET (vif));
     361           0 :   return mtu;
     362             : }
     363             : 
     364             : static void
     365           0 : virtio_pci_modern_read_config (vlib_main_t * vm, virtio_if_t * vif, void *dst,
     366             :                                int len, u32 addr)
     367             : {
     368             :   u8 config_count;
     369             :   do
     370             :     {
     371           0 :       config_count = virtio_pci_modern_get_config_generation (vif);
     372           0 :       virtio_pci_modern_get_device_mac (vm, vif);
     373           0 :       u16 status = virtio_pci_modern_get_device_status (vm, vif);
     374             :       u16 max_queue_pairs =
     375           0 :         virtio_pci_modern_get_max_virtqueue_pairs (vm, vif);
     376           0 :       u16 mtu = virtio_pci_modern_get_device_mtu (vm, vif);
     377           0 :       virtio_log_debug (vif, "status %u, max_queue_pairs %u, mtu %u", status,
     378             :                         max_queue_pairs, mtu);
     379             :     }
     380           0 :   while (config_count != virtio_pci_modern_get_config_generation (vif));
     381           0 : }
     382             : 
     383             : static void
     384           0 : virtio_pci_modern_write_config (vlib_main_t * vm, virtio_if_t * vif,
     385             :                                 void *src, int len, u32 addr)
     386             : {
     387             :   // do nothing
     388           0 : }
     389             : 
     390             : static u8
     391           0 : virtio_pci_modern_get_isr (vlib_main_t * vm, virtio_if_t * vif)
     392             : {
     393           0 :   return virtio_pci_reg_read_u8 (vif, VIRTIO_ISR_OFFSET (vif));
     394             : }
     395             : 
     396             : inline void
     397           0 : virtio_pci_modern_notify_queue (vlib_main_t * vm, virtio_if_t * vif,
     398             :                                 u16 queue_id, u16 queue_notify_off)
     399             : {
     400           0 :   virtio_pci_reg_write_u16 (vif,
     401           0 :                             VIRTIO_NOTIFICATION_OFFSET (vif) +
     402             :                             queue_notify_off, queue_id);
     403           0 : }
     404             : 
     405             : static void
     406           0 : virtio_pci_modern_device_debug_config_space (vlib_main_t * vm,
     407             :                                              virtio_if_t * vif)
     408             : {
     409             :   // do nothing for now
     410           0 : }
     411             : 
     412             : const virtio_pci_func_t virtio_pci_modern_func = {
     413             :   .read_config = virtio_pci_modern_read_config,
     414             :   .write_config = virtio_pci_modern_write_config,
     415             :   .get_device_features = virtio_pci_modern_get_device_features,
     416             :   .get_driver_features = virtio_pci_modern_get_driver_features,
     417             :   .set_driver_features = virtio_pci_modern_set_driver_features,
     418             :   .get_status = virtio_pci_modern_get_status,
     419             :   .set_status = virtio_pci_modern_set_status,
     420             :   .device_reset = virtio_pci_modern_reset,
     421             :   .get_isr = virtio_pci_modern_get_isr,
     422             :   .get_queue_size = virtio_pci_modern_get_queue_size,
     423             :   .set_queue_size = virtio_pci_modern_set_queue_size,
     424             :   .setup_queue = virtio_pci_modern_setup_queue,
     425             :   .del_queue = virtio_pci_modern_del_queue,
     426             :   .get_queue_notify_off = virtio_pci_modern_get_queue_notify_off,
     427             :   .notify_queue = virtio_pci_modern_notify_queue,
     428             :   .set_config_irq = virtio_pci_modern_set_msix_config,
     429             :   .set_queue_irq = virtio_pci_modern_set_queue_msix_vector,
     430             :   .get_mac = virtio_pci_modern_get_device_mac,
     431             :   .set_mac = virtio_pci_modern_set_device_mac,
     432             :   .get_device_status = virtio_pci_modern_get_device_status,
     433             :   .get_max_queue_pairs = virtio_pci_modern_get_max_virtqueue_pairs,
     434             :   .get_mtu = virtio_pci_modern_get_device_mtu,
     435             :   .device_debug_config_space = virtio_pci_modern_device_debug_config_space,
     436             : };
     437             : 
     438             : /*
     439             :  * fd.io coding-style-patch-verification: ON
     440             :  *
     441             :  * Local Variables:
     442             :  * eval: (c-set-style "gnu")
     443             :  * End:
     444             :  */

Generated by: LCOV version 1.14