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,31 +85,31 @@ static void virtqueue_init(VirtQueue *vq)
85 VIRTIO_PCI_VRING_ALIGN); 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 target_phys_addr_t pa; 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 return ldq_phys(pa); 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 target_phys_addr_t pa; 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 return ldl_phys(pa); 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 target_phys_addr_t pa; 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 return lduw_phys(pa); 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 target_phys_addr_t pa; 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 return lduw_phys(pa); 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,20 +269,21 @@ static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx)
269 return head; 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 unsigned int next; 275 unsigned int next;
275 276
276 /* If this descriptor says it doesn't chain, we're done. */ 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 /* Check they're not leading us off end of descriptors. */ 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 /* Make sure compiler knows to grab that: we don't want it changing! */ 283 /* Make sure compiler knows to grab that: we don't want it changing! */
283 wmb(); 284 wmb();
284 285
285 - if (next >= vq->vring.num) { 286 + if (next >= max) {
286 fprintf(stderr, "Desc next is %u", next); 287 fprintf(stderr, "Desc next is %u", next);
287 exit(1); 288 exit(1);
288 } 289 }
@@ -292,10 +293,12 @@ static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i) @@ -292,10 +293,12 @@ static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
292 293
293 int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) 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 int num_bufs, in_total, out_total; 298 int num_bufs, in_total, out_total;
297 299
298 idx = vq->last_avail_idx; 300 idx = vq->last_avail_idx;
  301 + max = vq->vring.num;
299 302
300 num_bufs = in_total = out_total = 0; 303 num_bufs = in_total = out_total = 0;
301 while (virtqueue_num_heads(vq, idx)) { 304 while (virtqueue_num_heads(vq, idx)) {
@@ -304,21 +307,21 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) @@ -304,21 +307,21 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
304 i = virtqueue_get_head(vq, idx++); 307 i = virtqueue_get_head(vq, idx++);
305 do { 308 do {
306 /* If we've got too many, that implies a descriptor loop. */ 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 fprintf(stderr, "Looped descriptor"); 311 fprintf(stderr, "Looped descriptor");
309 exit(1); 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 if (in_bytes > 0 && 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 return 1; 318 return 1;
316 } else { 319 } else {
317 if (out_bytes > 0 && 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 return 1; 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 return 0; 327 return 0;
@@ -326,7 +329,8 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) @@ -326,7 +329,8 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
326 329
327 int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) 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 target_phys_addr_t len; 334 target_phys_addr_t len;
331 335
332 if (!virtqueue_num_heads(vq, vq->last_avail_idx)) 336 if (!virtqueue_num_heads(vq, vq->last_avail_idx))
@@ -335,23 +339,26 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) @@ -335,23 +339,26 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
335 /* When we start there are none of either input nor output. */ 339 /* When we start there are none of either input nor output. */
336 elem->out_num = elem->in_num = 0; 340 elem->out_num = elem->in_num = 0;
337 341
  342 + max = vq->vring.num;
  343 +
338 i = head = virtqueue_get_head(vq, vq->last_avail_idx++); 344 i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
339 do { 345 do {
340 struct iovec *sg; 346 struct iovec *sg;
341 int is_write = 0; 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 sg = &elem->in_sg[elem->in_num++]; 351 sg = &elem->in_sg[elem->in_num++];
346 is_write = 1; 352 is_write = 1;
347 } else 353 } else
348 sg = &elem->out_sg[elem->out_num++]; 354 sg = &elem->out_sg[elem->out_num++];
349 355
350 /* Grab the first descriptor, and check it's OK. */ 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 len = sg->iov_len; 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 if (sg->iov_base == NULL || len != sg->iov_len) { 363 if (sg->iov_base == NULL || len != sg->iov_len) {
357 fprintf(stderr, "virtio: trying to map MMIO memory\n"); 364 fprintf(stderr, "virtio: trying to map MMIO memory\n");
@@ -359,11 +366,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) @@ -359,11 +366,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
359 } 366 }
360 367
361 /* If we've got too many, that implies a descriptor loop. */ 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 fprintf(stderr, "Looped descriptor"); 370 fprintf(stderr, "Looped descriptor");
364 exit(1); 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 elem->index = head; 375 elem->index = head;
369 376