Commit 5774cf98ca7da4161ee4265a2db0d92ffff005f3

Authored by Mark McLoughlin
Committed by Anthony Liguori
1 parent 024431b3

virtio: make vring_desc_*() take phys addrs

Change the vring descriptor helpers to take the physical
address of the descriptor table rather than a virtqueue.

This is needed in order to allow these helpers to be used
with an indirect descriptor table.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing 1 changed file with 33 additions and 26 deletions
hw/virtio.c
... ... @@ -85,31 +85,31 @@ static void virtqueue_init(VirtQueue *vq)
85 85 VIRTIO_PCI_VRING_ALIGN);
86 86 }
87 87  
88   -static inline uint64_t vring_desc_addr(VirtQueue *vq, int i)
  88 +static inline uint64_t vring_desc_addr(target_phys_addr_t desc_pa, int i)
89 89 {
90 90 target_phys_addr_t pa;
91   - pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr);
  91 + pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr);
92 92 return ldq_phys(pa);
93 93 }
94 94  
95   -static inline uint32_t vring_desc_len(VirtQueue *vq, int i)
  95 +static inline uint32_t vring_desc_len(target_phys_addr_t desc_pa, int i)
96 96 {
97 97 target_phys_addr_t pa;
98   - pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, len);
  98 + pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, len);
99 99 return ldl_phys(pa);
100 100 }
101 101  
102   -static inline uint16_t vring_desc_flags(VirtQueue *vq, int i)
  102 +static inline uint16_t vring_desc_flags(target_phys_addr_t desc_pa, int i)
103 103 {
104 104 target_phys_addr_t pa;
105   - pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags);
  105 + pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags);
106 106 return lduw_phys(pa);
107 107 }
108 108  
109   -static inline uint16_t vring_desc_next(VirtQueue *vq, int i)
  109 +static inline uint16_t vring_desc_next(target_phys_addr_t desc_pa, int i)
110 110 {
111 111 target_phys_addr_t pa;
112   - pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, next);
  112 + pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, next);
113 113 return lduw_phys(pa);
114 114 }
115 115  
... ... @@ -269,20 +269,21 @@ static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx)
269 269 return head;
270 270 }
271 271  
272   -static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
  272 +static unsigned virtqueue_next_desc(target_phys_addr_t desc_pa,
  273 + unsigned int i, unsigned int max)
273 274 {
274 275 unsigned int next;
275 276  
276 277 /* If this descriptor says it doesn't chain, we're done. */
277   - if (!(vring_desc_flags(vq, i) & VRING_DESC_F_NEXT))
278   - return vq->vring.num;
  278 + if (!(vring_desc_flags(desc_pa, i) & VRING_DESC_F_NEXT))
  279 + return max;
279 280  
280 281 /* Check they're not leading us off end of descriptors. */
281   - next = vring_desc_next(vq, i);
  282 + next = vring_desc_next(desc_pa, i);
282 283 /* Make sure compiler knows to grab that: we don't want it changing! */
283 284 wmb();
284 285  
285   - if (next >= vq->vring.num) {
  286 + if (next >= max) {
286 287 fprintf(stderr, "Desc next is %u", next);
287 288 exit(1);
288 289 }
... ... @@ -292,10 +293,12 @@ static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
292 293  
293 294 int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
294 295 {
295   - unsigned int idx;
  296 + target_phys_addr_t desc_pa = vq->vring.desc;
  297 + unsigned int idx, max;
296 298 int num_bufs, in_total, out_total;
297 299  
298 300 idx = vq->last_avail_idx;
  301 + max = vq->vring.num;
299 302  
300 303 num_bufs = in_total = out_total = 0;
301 304 while (virtqueue_num_heads(vq, idx)) {
... ... @@ -304,21 +307,21 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
304 307 i = virtqueue_get_head(vq, idx++);
305 308 do {
306 309 /* If we've got too many, that implies a descriptor loop. */
307   - if (++num_bufs > vq->vring.num) {
  310 + if (++num_bufs > max) {
308 311 fprintf(stderr, "Looped descriptor");
309 312 exit(1);
310 313 }
311 314  
312   - if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) {
  315 + if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
313 316 if (in_bytes > 0 &&
314   - (in_total += vring_desc_len(vq, i)) >= in_bytes)
  317 + (in_total += vring_desc_len(desc_pa, i)) >= in_bytes)
315 318 return 1;
316 319 } else {
317 320 if (out_bytes > 0 &&
318   - (out_total += vring_desc_len(vq, i)) >= out_bytes)
  321 + (out_total += vring_desc_len(desc_pa, i)) >= out_bytes)
319 322 return 1;
320 323 }
321   - } while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num);
  324 + } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
322 325 }
323 326  
324 327 return 0;
... ... @@ -326,7 +329,8 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
326 329  
327 330 int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
328 331 {
329   - unsigned int i, head;
  332 + unsigned int i, head, max;
  333 + target_phys_addr_t desc_pa = vq->vring.desc;
330 334 target_phys_addr_t len;
331 335  
332 336 if (!virtqueue_num_heads(vq, vq->last_avail_idx))
... ... @@ -335,23 +339,26 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
335 339 /* When we start there are none of either input nor output. */
336 340 elem->out_num = elem->in_num = 0;
337 341  
  342 + max = vq->vring.num;
  343 +
338 344 i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
339 345 do {
340 346 struct iovec *sg;
341 347 int is_write = 0;
342 348  
343   - if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) {
344   - elem->in_addr[elem->in_num] = vring_desc_addr(vq, i);
  349 + if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
  350 + elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i);
345 351 sg = &elem->in_sg[elem->in_num++];
346 352 is_write = 1;
347 353 } else
348 354 sg = &elem->out_sg[elem->out_num++];
349 355  
350 356 /* Grab the first descriptor, and check it's OK. */
351   - sg->iov_len = vring_desc_len(vq, i);
  357 + sg->iov_len = vring_desc_len(desc_pa, i);
352 358 len = sg->iov_len;
353 359  
354   - sg->iov_base = cpu_physical_memory_map(vring_desc_addr(vq, i), &len, is_write);
  360 + sg->iov_base = cpu_physical_memory_map(vring_desc_addr(desc_pa, i),
  361 + &len, is_write);
355 362  
356 363 if (sg->iov_base == NULL || len != sg->iov_len) {
357 364 fprintf(stderr, "virtio: trying to map MMIO memory\n");
... ... @@ -359,11 +366,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
359 366 }
360 367  
361 368 /* If we've got too many, that implies a descriptor loop. */
362   - if ((elem->in_num + elem->out_num) > vq->vring.num) {
  369 + if ((elem->in_num + elem->out_num) > max) {
363 370 fprintf(stderr, "Looped descriptor");
364 371 exit(1);
365 372 }
366   - } while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num);
  373 + } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
367 374  
368 375 elem->index = head;
369 376  
... ...