Commit 5774cf98ca7da4161ee4265a2db0d92ffff005f3
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 | ... | ... |