FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
virtio_pci_legacy.c
Go to the documentation of this file.
1 /*
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:
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 <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>
24 
25 #define PCI_CONFIG_SIZE(vif) ((vif->msix_enabled == VIRTIO_MSIX_ENABLED) ? \
26  24 : 20)
27 
28 static void
30  int len, u32 addr)
31 {
32  u32 size = 0;
34 
35  while (len > 0)
36  {
37  if (len >= 4)
38  {
39  size = 4;
40  vlib_pci_read_io_u32 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
41  }
42  else if (len >= 2)
43  {
44  size = 2;
45  vlib_pci_read_io_u16 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
46  }
47  else
48  {
49  size = 1;
50  vlib_pci_read_io_u8 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
51  }
52  dst = (u8 *) dst + size;
53  addr += size;
54  len -= size;
55  }
56 }
57 
58 static void
60  void *src, int len, u32 addr)
61 {
62  u32 size = 0;
64 
65  while (len > 0)
66  {
67  if (len >= 4)
68  {
69  size = 4;
70  vlib_pci_write_io_u32 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
71  }
72  else if (len >= 2)
73  {
74  size = 2;
75  vlib_pci_write_io_u16 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
76  }
77  else
78  {
79  size = 1;
80  vlib_pci_write_io_u8 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
81  }
82  src = (u8 *) src + size;
83  addr += size;
84  len -= size;
85  }
86 }
87 
88 static u64
90 {
91  u32 host_features;
92  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_HOST_FEATURES,
93  &host_features);
94  return host_features;
95 }
96 
97 static u64
99 {
100  u32 guest_features = 0;
101  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
102  &guest_features);
103  vif->features = guest_features;
104  return guest_features;
105 }
106 
107 static void
109  u64 guest_features)
110 {
111  if ((guest_features >> 32) != 0)
112  {
113  clib_warning ("only 32 bit features are allowed for legacy virtio!");
114  }
115  u32 features = 0;
116  u32 gf = (u32) guest_features;
117 
118  vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
119  &gf);
120  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
121  &features);
122  if (features != (u32) guest_features)
123  {
124  clib_warning ("legacy set guest features failed!");
125  }
126 }
127 
128 static u8
130 {
131  u8 status = 0;
132  vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_STATUS, &status);
133  return status;
134 }
135 
136 static void
138 {
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);
142 }
143 
144 static u8
146 {
147  virtio_pci_legacy_set_status (vm, vif, VIRTIO_CONFIG_STATUS_RESET);
148  return virtio_pci_legacy_get_status (vm, vif);
149 }
150 
151 static u8
153 {
154  u8 isr = 0;
155  vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_ISR, &isr);
156  return isr;
157 }
158 
159 static u16
161  u16 queue_id)
162 {
163  u16 queue_num = 0;
164  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
165  &queue_id);
166  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NUM,
167  &queue_num);
168  return queue_num;
169 }
170 
171 static void
173  u16 queue_id, u16 queue_size)
174 {
175  /* do nothing */
176 }
177 
178 static u8
180  u16 queue_id, void *p)
181 {
183  u32 addr2 = 0, a = (u32) addr;
184  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
185  &queue_id);
186  vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN, &a);
187  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN,
188  &addr2);
189  if (addr == addr2)
190  return 0;
191 
192  clib_warning ("legacy queue setup failed!");
193  return 1;
194 }
195 
196 static void
198  u16 queue_id)
199 {
200  u32 src = 0;
201  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
202  &queue_id);
203  vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN, &src);
204 }
205 
206 static u16
208  u16 queue_id)
209 {
210  return 0;
211 }
212 
213 inline void
215  u16 queue_id, u16 queue_notify_off)
216 {
217  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NOTIFY,
218  &queue_id);
219 }
220 
221 /* Enable one vector (0) for Link State Intrerrupt */
222 static u16
224  u16 vec)
225 {
226  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
227  &vec);
228  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
229  &vec);
230  return vec;
231 }
232 
233 static u16
235  u16 queue_id)
236 {
237  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
238  &queue_id);
239  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
240  &vec);
241  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
242  &vec);
243  return vec;
244 }
245 
246 static void
248 {
250  sizeof (vif->mac_addr), 0);
251 }
252 
253 static void
255 {
257  sizeof (vif->mac_addr), 0);
258 }
259 
260 static u16
262 {
263  u16 status = 0;
264  virtio_pci_legacy_read_config (vm, vif, &status,
265  sizeof (status),
267  (virtio_net_config_t, status));
268  return status;
269 }
270 
271 static u16
273 {
274  virtio_net_config_t config;
276  sizeof (config.max_virtqueue_pairs),
278  (virtio_net_config_t, max_virtqueue_pairs));
279  return config.max_virtqueue_pairs;
280 }
281 
282 static u16
284 {
285  virtio_net_config_t config;
286  virtio_pci_legacy_read_config (vm, vif, &config.mtu,
287  sizeof (config.mtu),
289  return config.mtu;
290 }
291 
292 
293 static void
295  virtio_if_t * vif)
296 {
297  u32 data_u32;
298  u16 data_u16;
299  u8 data_u8;
300  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_HOST_FEATURES,
301  &data_u32);
302  vlib_cli_output (vm, "remote features 0x%lx", data_u32);
303  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
304  &data_u32);
305  vlib_cli_output (vm, "guest features 0x%lx", data_u32);
306  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN,
307  &data_u32);
308  vlib_cli_output (vm, "queue address 0x%lx", data_u32);
309  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NUM,
310  &data_u16);
311  vlib_cli_output (vm, "queue size 0x%x", data_u16);
312  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
313  &data_u16);
314  vlib_cli_output (vm, "queue select 0x%x", data_u16);
315  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NOTIFY,
316  &data_u16);
317  vlib_cli_output (vm, "queue notify 0x%x", data_u16);
318  vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_STATUS, &data_u8);
319  vlib_cli_output (vm, "status 0x%x", data_u8);
320  vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_ISR, &data_u8);
321  vlib_cli_output (vm, "isr 0x%x", data_u8);
322 
323  if (vif->msix_enabled == VIRTIO_MSIX_ENABLED)
324  {
325  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
326  &data_u16);
327  vlib_cli_output (vm, "config vector 0x%x", data_u16);
328  u16 queue_id = 0;
329  vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
330  &queue_id);
331  vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
332  &data_u16);
333  vlib_cli_output (vm, "queue vector for queue (0) 0x%x", data_u16);
334  }
335 
336  u8 mac[6];
337  virtio_pci_legacy_read_config (vm, vif, mac, sizeof (mac), 0);
338  vlib_cli_output (vm, "mac %U", format_ethernet_address, mac);
339  virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16), /* offset to status */
340  6);
341  vlib_cli_output (vm, "link up/down status 0x%x", data_u16);
342  virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16),
343  /* offset to max_virtqueue */ 8);
344  vlib_cli_output (vm, "num of virtqueue 0x%x", data_u16);
345  virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16), /* offset to mtu */
346  10);
347  vlib_cli_output (vm, "mtu 0x%x", data_u16);
348 
349  u32 i = PCI_CONFIG_SIZE (vif) + 12, a = 4;
350  i += a;
351  i &= ~a;
352  for (; i < 64; i += 4)
353  {
354  u32 data = 0;
355  vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, i, &data);
356  vlib_cli_output (vm, "0x%lx", data);
357  }
358 }
359 
361  .read_config = virtio_pci_legacy_read_config,
362  .write_config = virtio_pci_legacy_write_config,
363  .get_device_features = virtio_pci_legacy_get_host_features,
364  .get_driver_features = virtio_pci_legacy_get_guest_features,
365  .set_driver_features = virtio_pci_legacy_set_guest_features,
366  .get_status = virtio_pci_legacy_get_status,
367  .set_status = virtio_pci_legacy_set_status,
368  .device_reset = virtio_pci_legacy_reset,
369  .get_isr = virtio_pci_legacy_get_isr,
370  .get_queue_size = virtio_pci_legacy_get_queue_num,
371  .set_queue_size = virtio_pci_legacy_set_queue_num,
372  .setup_queue = virtio_pci_legacy_setup_queue,
373  .del_queue = virtio_pci_legacy_del_queue,
374  .get_queue_notify_off = virtio_pci_legacy_get_queue_notify_off,
375  .notify_queue = virtio_pci_legacy_notify_queue,
376  .set_config_irq = virtio_pci_legacy_set_config_irq,
377  .set_queue_irq = virtio_pci_legacy_set_queue_irq,
378  .get_mac = virtio_pci_legacy_get_mac,
379  .set_mac = virtio_pci_legacy_set_mac,
380  .get_device_status = virtio_pci_legacy_get_device_status,
381  .get_max_queue_pairs = virtio_pci_legacy_get_max_queue_pairs,
382  .get_mtu = virtio_pci_legacy_get_mtu,
383  .device_debug_config_space = virtio_pci_legacy_device_debug_config_space,
384 };
385 
386 /*
387  * fd.io coding-style-patch-verification: ON
388  *
389  * Local Variables:
390  * eval: (c-set-style "gnu")
391  * End:
392  */
static void virtio_pci_legacy_write_config(vlib_main_t *vm, virtio_if_t *vif, void *src, int len, u32 addr)
#define VIRTIO_PCI_STATUS
static u16 virtio_pci_legacy_get_device_status(vlib_main_t *vm, virtio_if_t *vif)
vl_api_mac_address_t mac
Definition: l2.api:502
#define VIRTIO_MSI_CONFIG_VECTOR
a
Definition: bitmap.h:538
u16 max_virtqueue_pairs
Definition: pci.h:146
unsigned long u64
Definition: types.h:89
static void virtio_pci_legacy_del_queue(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id)
static void virtio_pci_legacy_set_status(vlib_main_t *vm, virtio_if_t *vif, u8 status)
vl_api_address_t src
Definition: gre.api:54
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:70
vlib_main_t * vm
Definition: in2out_ed.c:1582
vhost_vring_addr_t addr
Definition: vhost_user.h:111
#define VIRTIO_PCI_QUEUE_SEL
unsigned char u8
Definition: types.h:56
u8 data[128]
Definition: ipsec_types.api:89
u32 msix_enabled
Definition: virtio.h:122
static u8 virtio_pci_legacy_get_isr(vlib_main_t *vm, virtio_if_t *vif)
u64 features
Definition: virtio.h:107
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
#define VIRTIO_PCI_QUEUE_NOTIFY
static void virtio_pci_legacy_set_mac(vlib_main_t *vm, virtio_if_t *vif)
static u16 virtio_pci_legacy_set_config_irq(vlib_main_t *vm, virtio_if_t *vif, u16 vec)
unsigned int u32
Definition: types.h:88
static u64 virtio_pci_legacy_get_guest_features(vlib_main_t *vm, virtio_if_t *vif)
u32 pci_dev_handle
Definition: virtio.h:121
static void virtio_pci_legacy_set_queue_num(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id, u16 queue_size)
#define VIRTIO_PCI_HOST_FEATURES
unsigned short u16
Definition: types.h:57
u32 size
Definition: vhost_user.h:106
vec_header_t h
Definition: buffer.c:322
#define VIRTIO_PCI_QUEUE_PFN
static void virtio_pci_legacy_device_debug_config_space(vlib_main_t *vm, virtio_if_t *vif)
u32 vlib_pci_dev_handle_t
Definition: pci.h:97
vl_api_address_t dst
Definition: gre.api:55
u8 len
Definition: ip_types.api:92
static void virtio_pci_legacy_read_config(vlib_main_t *vm, virtio_if_t *vif, void *dst, int len, u32 addr)
#define VIRTIO_MSI_QUEUE_VECTOR
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define clib_warning(format, args...)
Definition: error.h:59
#define VIRTIO_PCI_QUEUE_NUM
u8 mac_addr[6]
Definition: virtio.h:146
const virtio_pci_func_t virtio_pci_legacy_func
#define VIRTIO_PCI_GUEST_FEATURES
static u8 virtio_pci_legacy_get_status(vlib_main_t *vm, virtio_if_t *vif)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
static void virtio_pci_legacy_set_guest_features(vlib_main_t *vm, virtio_if_t *vif, u64 guest_features)
static void virtio_pci_legacy_get_mac(vlib_main_t *vm, virtio_if_t *vif)
static u16 virtio_pci_legacy_get_queue_num(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id)
static u64 vlib_physmem_get_pa(vlib_main_t *vm, void *mem)
struct _virtio_pci_func virtio_pci_func_t
#define VIRTIO_PCI_ISR
static u8 virtio_pci_legacy_setup_queue(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id, void *p)
static u16 virtio_pci_legacy_set_queue_irq(vlib_main_t *vm, virtio_if_t *vif, u16 vec, u16 queue_id)
static u16 virtio_pci_legacy_get_queue_notify_off(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id)
void virtio_pci_legacy_notify_queue(vlib_main_t *vm, virtio_if_t *vif, u16 queue_id, u16 queue_notify_off)
static u16 virtio_pci_legacy_get_max_queue_pairs(vlib_main_t *vm, virtio_if_t *vif)
#define PCI_CONFIG_SIZE(vif)
static u8 virtio_pci_legacy_reset(vlib_main_t *vm, virtio_if_t *vif)
static u64 virtio_pci_legacy_get_host_features(vlib_main_t *vm, virtio_if_t *vif)
static u16 virtio_pci_legacy_get_mtu(vlib_main_t *vm, virtio_if_t *vif)
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT
Definition: pci.h:88