iPXE
virtio-ring.c
Go to the documentation of this file.
1 /* virtio-pci.c - virtio ring management
2  *
3  * (c) Copyright 2008 Bull S.A.S.
4  *
5  * Author: Laurent Vivier <Laurent.Vivier@bull.net>
6  *
7  * some parts from Linux Virtio Ring
8  *
9  * Copyright Rusty Russell IBM Corporation 2007
10  *
11  * This work is licensed under the terms of the GNU GPL, version 2 or later.
12  * See the COPYING file in the top-level directory.
13  *
14  *
15  */
16 
17 FILE_LICENCE ( GPL2_OR_LATER );
18 
19 #include "etherboot.h"
20 #include "ipxe/io.h"
21 #include "ipxe/virtio-pci.h"
22 #include "ipxe/virtio-ring.h"
23 
24 #define BUG() do { \
25  printf("BUG: failure at %s:%d/%s()!\n", \
26  __FILE__, __LINE__, __FUNCTION__); \
27  while(1); \
28 } while (0)
29 #define BUG_ON(condition) do { if (condition) BUG(); } while (0)
30 
31 /*
32  * vring_free
33  *
34  * put at the begin of the free list the current desc[head]
35  */
36 
37 void vring_detach(struct vring_virtqueue *vq, unsigned int head)
38 {
39  struct vring *vr = &vq->vring;
40  unsigned int i;
41 
42  /* find end of given descriptor */
43 
44  i = head;
45  while (vr->desc[i].flags & VRING_DESC_F_NEXT)
46  i = vr->desc[i].next;
47 
48  /* link it with free list and point to it */
49 
50  vr->desc[i].next = vq->free_head;
51  wmb();
52  vq->free_head = head;
53 }
54 
55 /*
56  * vring_get_buf
57  *
58  * get a buffer from the used list
59  *
60  */
61 
62 void *vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
63 {
64  struct vring *vr = &vq->vring;
65  struct vring_used_elem *elem;
66  u32 id;
67  void *opaque;
68 
69  BUG_ON(!vring_more_used(vq));
70 
71  elem = &vr->used->ring[vq->last_used_idx % vr->num];
72  wmb();
73  id = elem->id;
74  if (len != NULL)
75  *len = elem->len;
76 
77  opaque = vq->vdata[id];
78 
79  vring_detach(vq, id);
80 
81  vq->last_used_idx++;
82 
83  return opaque;
84 }
85 
87  struct vring_list list[],
88  unsigned int out, unsigned int in,
89  void *opaque, int num_added)
90 {
91  struct vring *vr = &vq->vring;
92  int i, avail, head, prev;
93 
94  BUG_ON(out + in == 0);
95 
96  prev = 0;
97  head = vq->free_head;
98  for (i = head; out; i = vr->desc[i].next, out--) {
99 
100  vr->desc[i].flags = VRING_DESC_F_NEXT;
101  vr->desc[i].addr = (u64)virt_to_phys(list->addr);
102  vr->desc[i].len = list->length;
103  prev = i;
104  list++;
105  }
106  for ( ; in; i = vr->desc[i].next, in--) {
107 
109  vr->desc[i].addr = (u64)virt_to_phys(list->addr);
110  vr->desc[i].len = list->length;
111  prev = i;
112  list++;
113  }
114  vr->desc[prev].flags &= ~VRING_DESC_F_NEXT;
115 
116  vq->free_head = i;
117 
118  vq->vdata[head] = opaque;
119 
120  avail = (vr->avail->idx + num_added) % vr->num;
121  vr->avail->ring[avail] = head;
122  wmb();
123 }
124 
125 void vring_kick(struct virtio_pci_modern_device *vdev, unsigned int ioaddr,
126  struct vring_virtqueue *vq, int num_added)
127 {
128  struct vring *vr = &vq->vring;
129 
130  wmb();
131  vr->avail->idx += num_added;
132 
133  mb();
134  if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY)) {
135  if (vdev) {
136  /* virtio 1.0 */
137  vpm_notify(vdev, vq);
138  } else {
139  /* legacy virtio */
141  }
142  }
143 }
void vring_kick(struct virtio_pci_modern_device *vdev, unsigned int ioaddr, struct vring_virtqueue *vq, int num_added)
Definition: virtio-ring.c:125
iPXE I/O API
wmb()
static int vring_more_used(struct vring_virtqueue *vq)
Definition: virtio-ring.h:136
struct vring vring
Definition: virtio-ring.h:77
__be32 in[4]
Definition: CIB_PRM.h:35
#define BUG_ON(condition)
Definition: virtio-ring.c:29
#define VRING_DESC_F_WRITE
Definition: virtio-ring.h:28
struct vring_avail * avail
Definition: virtio-ring.h:65
struct vring_used_elem ring[]
Definition: virtio-ring.h:59
void vring_detach(struct vring_virtqueue *vq, unsigned int head)
Definition: virtio-ring.c:37
uint8_t head
Head number.
Definition: int13.h:34
static __always_inline unsigned long virt_to_phys(volatile const void *addr)
Convert virtual address to a physical address.
Definition: uaccess.h:287
static void vp_notify(unsigned int ioaddr, int queue_index)
Definition: virtio-pci.h:181
void vpm_notify(struct virtio_pci_modern_device *vdev, struct vring_virtqueue *vq)
Definition: virtio-pci.c:344
static unsigned long ioaddr
Definition: davicom.c:129
uint64_t u64
Definition: stdint.h:25
__be32 out[4]
Definition: CIB_PRM.h:36
u16 ring[0]
Definition: virtio-ring.h:46
uint8_t id
Request identifier.
Definition: ena.h:12
#define VRING_USED_F_NO_NOTIFY
Definition: virtio-ring.h:32
void * vring_get_buf(struct vring_virtqueue *vq, unsigned int *len)
Definition: virtio-ring.c:62
unsigned int num
Definition: virtio-ring.h:63
struct vring_desc * desc
Definition: virtio-ring.h:64
FILE_LICENCE(GPL2_OR_LATER)
#define VRING_DESC_F_NEXT
Definition: virtio-ring.h:27
uint32_t len
Length.
Definition: ena.h:14
unsigned int length
Definition: virtio-ring.h:88
void mb(void)
Memory barrier.
struct vring_used * used
Definition: virtio-ring.h:66
void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[], unsigned int out, unsigned int in, void *opaque, int num_added)
Definition: virtio-ring.c:86
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
uint32_t u32
Definition: stdint.h:23
char * addr
Definition: virtio-ring.h:87